From 7c19058d2a8e05383988b92cf4004c4cd8a54951 Mon Sep 17 00:00:00 2001 From: Steven Wu Date: Tue, 21 May 2024 09:15:37 -0700 Subject: [PATCH 001/452] [Darwin][IR] Don't error on target_variant mismatch when linking IR (#92297) Change the ModuleFlag type for target_variant to warning to avoid error out when the value is different. This matches the linker behavior when linking object files. rdar://125874272 --- clang/test/CodeGen/darwin-target-variant.c | 2 +- llvm/lib/IR/Module.cpp | 2 +- llvm/test/Linker/darwin-target-variant.ll | 42 +++++++++++++++++++ .../MC/MachO/darwin-target-variant-reverse.ll | 2 +- llvm/test/MC/MachO/darwin-target-variant.ll | 2 +- 5 files changed, 46 insertions(+), 4 deletions(-) create mode 100644 llvm/test/Linker/darwin-target-variant.ll diff --git a/clang/test/CodeGen/darwin-target-variant.c b/clang/test/CodeGen/darwin-target-variant.c index 36caaaec1bdb..9f4b36a790db 100644 --- a/clang/test/CodeGen/darwin-target-variant.c +++ b/clang/test/CodeGen/darwin-target-variant.c @@ -2,5 +2,5 @@ // CHECK: !llvm.module.flags = !{!0, !1, !2 // CHECK: !0 = !{i32 2, !"SDK Version", [2 x i32] [i32 11, i32 1]} -// CHECK: !1 = !{i32 4, !"darwin.target_variant.triple", !"x86_64-apple-ios14-macabi"} +// CHECK: !1 = !{i32 2, !"darwin.target_variant.triple", !"x86_64-apple-ios14-macabi"} // CHECK: !2 = !{i32 2, !"darwin.target_variant.SDK Version", [2 x i32] [i32 14, i32 1]} diff --git a/llvm/lib/IR/Module.cpp b/llvm/lib/IR/Module.cpp index a8696ed9e3ce..f97dd18c736c 100644 --- a/llvm/lib/IR/Module.cpp +++ b/llvm/lib/IR/Module.cpp @@ -882,7 +882,7 @@ StringRef Module::getDarwinTargetVariantTriple() const { } void Module::setDarwinTargetVariantTriple(StringRef T) { - addModuleFlag(ModFlagBehavior::Override, "darwin.target_variant.triple", + addModuleFlag(ModFlagBehavior::Warning, "darwin.target_variant.triple", MDString::get(getContext(), T)); } diff --git a/llvm/test/Linker/darwin-target-variant.ll b/llvm/test/Linker/darwin-target-variant.ll new file mode 100644 index 000000000000..7d46b2dda4a9 --- /dev/null +++ b/llvm/test/Linker/darwin-target-variant.ll @@ -0,0 +1,42 @@ +; RUN: rm -rf %t && split-file %s %t +; RUN: llvm-link %t/1.ll %t/2.ll -S -o - | FileCheck %s +; CHECK: {i32 2, !"darwin.target_variant.triple", !"x86_64-apple-ios13.1-macabi"} + +; RUN: llvm-link %t/1.ll %t/old.ll -S -o - | FileCheck %s -check-prefix OLD +; OLD: {i32 4, !"darwin.target_variant.triple", !"x86_64-apple-ios14.0-macabi"} + +;--- 1.ll +target triple = "x86_64-apple-macos10.15"; +!llvm.module.flags = !{!0, !1, !2}; +!0 = !{i32 2, !"SDK Version", [3 x i32] [ i32 10, i32 15, i32 1 ] }; +!1 = !{i32 2, !"darwin.target_variant.triple", !"x86_64-apple-ios13.1-macabi"}; +!2 = !{i32 2, !"darwin.target_variant.SDK Version", [2 x i32] [ i32 13, i32 2 ] }; + +define void @foo() { +entry: + ret void +} + +;--- 2.ll +target triple = "x86_64-apple-macos10.15"; +!llvm.module.flags = !{!0, !1, !2}; +!0 = !{i32 2, !"SDK Version", [3 x i32] [ i32 10, i32 15, i32 1 ] }; +!1 = !{i32 2, !"darwin.target_variant.triple", !"x86_64-apple-ios14.0-macabi"}; +!2 = !{i32 2, !"darwin.target_variant.SDK Version", [2 x i32] [ i32 13, i32 2 ] }; + +define void @bar() { +entry: + ret void +} + +;--- old.ll +target triple = "x86_64-apple-macos10.15"; +!llvm.module.flags = !{!0, !1, !2}; +!0 = !{i32 2, !"SDK Version", [3 x i32] [ i32 10, i32 15, i32 1 ] }; +!1 = !{i32 4, !"darwin.target_variant.triple", !"x86_64-apple-ios14.0-macabi"}; +!2 = !{i32 2, !"darwin.target_variant.SDK Version", [2 x i32] [ i32 13, i32 2 ] }; + +define void @old() { +entry: + ret void +} diff --git a/llvm/test/MC/MachO/darwin-target-variant-reverse.ll b/llvm/test/MC/MachO/darwin-target-variant-reverse.ll index 6d51cd8fffa8..fd527b204546 100644 --- a/llvm/test/MC/MachO/darwin-target-variant-reverse.ll +++ b/llvm/test/MC/MachO/darwin-target-variant-reverse.ll @@ -3,7 +3,7 @@ target triple = "x86_64-apple-ios13.1-macabi"; !llvm.module.flags = !{!0, !1, !2}; !0 = !{i32 2, !"SDK Version", [2 x i32] [ i32 13, i32 1 ] }; -!1 = !{i32 1, !"darwin.target_variant.triple", !"x86_64-apple-macos10.15"}; +!1 = !{i32 2, !"darwin.target_variant.triple", !"x86_64-apple-macos10.15"}; !2 = !{i32 2, !"darwin.target_variant.SDK Version", [2 x i32] [ i32 10, i32 15 ] }; define void @foo() { diff --git a/llvm/test/MC/MachO/darwin-target-variant.ll b/llvm/test/MC/MachO/darwin-target-variant.ll index d506ed92c9cc..78bd1e98410f 100644 --- a/llvm/test/MC/MachO/darwin-target-variant.ll +++ b/llvm/test/MC/MachO/darwin-target-variant.ll @@ -4,7 +4,7 @@ target triple = "x86_64-apple-macos10.15"; !llvm.module.flags = !{!0, !1, !2}; !0 = !{i32 2, !"SDK Version", [3 x i32] [ i32 10, i32 15, i32 1 ] }; -!1 = !{i32 1, !"darwin.target_variant.triple", !"x86_64-apple-ios13.1-macabi"}; +!1 = !{i32 2, !"darwin.target_variant.triple", !"x86_64-apple-ios13.1-macabi"}; !2 = !{i32 2, !"darwin.target_variant.SDK Version", [2 x i32] [ i32 13, i32 2 ] }; define void @foo() { -- GitLab From f52d29c9ab7d3c712d36c28d00adc95fe7d52805 Mon Sep 17 00:00:00 2001 From: Momchil Velikov Date: Tue, 21 May 2024 17:16:11 +0100 Subject: [PATCH 002/452] [Clang][Sema] Refactor handling of vector subscript expressions (NFC) (#92778) --- clang/include/clang/AST/Type.h | 5 ++++ clang/lib/Sema/SemaExpr.cpp | 44 +++++++++++----------------------- 2 files changed, 19 insertions(+), 30 deletions(-) diff --git a/clang/include/clang/AST/Type.h b/clang/include/clang/AST/Type.h index da3834f19ca0..9a5c6e8d562c 100644 --- a/clang/include/clang/AST/Type.h +++ b/clang/include/clang/AST/Type.h @@ -2523,6 +2523,7 @@ public: bool isVectorType() const; // GCC vector type. bool isExtVectorType() const; // Extended vector type. bool isExtVectorBoolType() const; // Extended vector type with bool element. + bool isSubscriptableVectorType() const; bool isMatrixType() const; // Matrix type. bool isConstantMatrixType() const; // Constant matrix type. bool isDependentAddressSpaceType() const; // value-dependent address space qualifier @@ -7729,6 +7730,10 @@ inline bool Type::isExtVectorBoolType() const { return cast(CanonicalType)->getElementType()->isBooleanType(); } +inline bool Type::isSubscriptableVectorType() const { + return isVectorType() || isSveVLSBuiltinType(); +} + inline bool Type::isMatrixType() const { return isa(CanonicalType); } diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index 7bb34fd7a479..326879b0883f 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -5241,36 +5241,22 @@ Sema::CreateBuiltinArraySubscriptExpr(Expr *Base, SourceLocation LLoc, << ResultType << BaseExpr->getSourceRange(); return ExprError(); } - } else if (const VectorType *VTy = LHSTy->getAs()) { - BaseExpr = LHSExp; // vectors: V[123] - IndexExpr = RHSExp; - // We apply C++ DR1213 to vector subscripting too. - if (getLangOpts().CPlusPlus11 && LHSExp->isPRValue()) { - ExprResult Materialized = TemporaryMaterializationConversion(LHSExp); - if (Materialized.isInvalid()) - return ExprError(); - LHSExp = Materialized.get(); + } else if (LHSTy->isSubscriptableVectorType()) { + if (LHSTy->isBuiltinType() && + LHSTy->getAs()->isSveVLSBuiltinType()) { + const BuiltinType *BTy = LHSTy->getAs(); + if (BTy->isSVEBool()) + return ExprError(Diag(LLoc, diag::err_subscript_svbool_t) + << LHSExp->getSourceRange() + << RHSExp->getSourceRange()); + ResultType = BTy->getSveEltType(Context); + } else { + const VectorType *VTy = LHSTy->getAs(); + ResultType = VTy->getElementType(); } - VK = LHSExp->getValueKind(); - if (VK != VK_PRValue) - OK = OK_VectorComponent; - - ResultType = VTy->getElementType(); - QualType BaseType = BaseExpr->getType(); - Qualifiers BaseQuals = BaseType.getQualifiers(); - Qualifiers MemberQuals = ResultType.getQualifiers(); - Qualifiers Combined = BaseQuals + MemberQuals; - if (Combined != MemberQuals) - ResultType = Context.getQualifiedType(ResultType, Combined); - } else if (LHSTy->isBuiltinType() && - LHSTy->getAs()->isSveVLSBuiltinType()) { - const BuiltinType *BTy = LHSTy->getAs(); - if (BTy->isSVEBool()) - return ExprError(Diag(LLoc, diag::err_subscript_svbool_t) - << LHSExp->getSourceRange() << RHSExp->getSourceRange()); - - BaseExpr = LHSExp; + BaseExpr = LHSExp; // vectors: V[123] IndexExpr = RHSExp; + // We apply C++ DR1213 to vector subscripting too. if (getLangOpts().CPlusPlus11 && LHSExp->isPRValue()) { ExprResult Materialized = TemporaryMaterializationConversion(LHSExp); if (Materialized.isInvalid()) @@ -5281,8 +5267,6 @@ Sema::CreateBuiltinArraySubscriptExpr(Expr *Base, SourceLocation LLoc, if (VK != VK_PRValue) OK = OK_VectorComponent; - ResultType = BTy->getSveEltType(Context); - QualType BaseType = BaseExpr->getType(); Qualifiers BaseQuals = BaseType.getQualifiers(); Qualifiers MemberQuals = ResultType.getQualifiers(); -- GitLab From ea43a30899df5c3c36412392c8f4db79973a1c43 Mon Sep 17 00:00:00 2001 From: Jeffrey Byrnes Date: Tue, 21 May 2024 09:21:36 -0700 Subject: [PATCH 003/452] [AMDGPU] Vectorize more 16 bit shuffles (#90648) In the case of larger vectors, we should still prefer the vectorized version (i.e. shufflevector vs extract/insert chains). In arithmetic chains, vectorization results in chains of packed math instructions (as opposed to unpack/repack & scalarized arithmetic): https://godbolt.org/z/c5onaf6G5 In chains with PHIs, vectorization again removes the unnecessary pack / repack code around BBs: https://godbolt.org/z/vz7zYzvhs --- .../AMDGPU/AMDGPUTargetTransformInfo.cpp | 65 +- .../CostModel/AMDGPU/shufflevector.ll | 1621 +++++++++++------ .../AMDGPU/add_sub_sat-inseltpoison.ll | 64 +- .../SLPVectorizer/AMDGPU/add_sub_sat.ll | 64 +- .../AMDGPU/crash_extract_subvector_cost.ll | 13 +- .../AMDGPU/phi-result-use-order.ll | 46 +- .../SLPVectorizer/AMDGPU/reduction.ll | 129 +- 7 files changed, 1278 insertions(+), 724 deletions(-) diff --git a/llvm/lib/Target/AMDGPU/AMDGPUTargetTransformInfo.cpp b/llvm/lib/Target/AMDGPU/AMDGPUTargetTransformInfo.cpp index 84320d296a03..437e01c37c6b 100644 --- a/llvm/lib/Target/AMDGPU/AMDGPUTargetTransformInfo.cpp +++ b/llvm/lib/Target/AMDGPU/AMDGPUTargetTransformInfo.cpp @@ -1129,31 +1129,56 @@ InstructionCost GCNTTIImpl::getShuffleCost(TTI::ShuffleKind Kind, int Index, VectorType *SubTp, ArrayRef Args, const Instruction *CxtI) { + if (!isa(VT)) + return BaseT::getShuffleCost(Kind, VT, Mask, CostKind, Index, SubTp); + Kind = improveShuffleKindFromMask(Kind, Mask, VT, Index, SubTp); - // Treat extractsubvector as single op permutation. - bool IsExtractSubvector = Kind == TTI::SK_ExtractSubvector; - if (IsExtractSubvector) - Kind = TTI::SK_PermuteSingleSrc; - - if (ST->hasVOP3PInsts()) { - if (cast(VT)->getNumElements() == 2 && - DL.getTypeSizeInBits(VT->getElementType()) == 16) { - // With op_sel VOP3P instructions freely can access the low half or high - // half of a register, so any swizzle is free. - switch (Kind) { - case TTI::SK_Broadcast: - case TTI::SK_Reverse: - case TTI::SK_PermuteSingleSrc: + // Larger vector widths may require additional instructions, but are + // typically cheaper than scalarized versions. + unsigned NumVectorElts = cast(VT)->getNumElements(); + if (ST->getGeneration() >= AMDGPUSubtarget::VOLCANIC_ISLANDS && + DL.getTypeSizeInBits(VT->getElementType()) == 16) { + bool HasVOP3P = ST->hasVOP3PInsts(); + unsigned RequestedElts = + count_if(Mask, [](int MaskElt) { return MaskElt != -1; }); + if (RequestedElts == 0) + return 0; + switch (Kind) { + case TTI::SK_Broadcast: + case TTI::SK_Reverse: + case TTI::SK_PermuteSingleSrc: { + // With op_sel VOP3P instructions freely can access the low half or high + // half of a register, so any swizzle of two elements is free. + if (HasVOP3P && NumVectorElts == 2) return 0; - default: - break; - } + unsigned NumPerms = alignTo(RequestedElts, 2) / 2; + // SK_Broadcast just reuses the same mask + unsigned NumPermMasks = Kind == TTI::SK_Broadcast ? 1 : NumPerms; + return NumPerms + NumPermMasks; + } + case TTI::SK_ExtractSubvector: + case TTI::SK_InsertSubvector: { + // Even aligned accesses are free + if (!(Index % 2)) + return 0; + // Insert/extract subvectors only require shifts / extract code to get the + // relevant bits + return alignTo(RequestedElts, 2) / 2; + } + case TTI::SK_PermuteTwoSrc: + case TTI::SK_Splice: + case TTI::SK_Select: { + unsigned NumPerms = alignTo(RequestedElts, 2) / 2; + // SK_Select just reuses the same mask + unsigned NumPermMasks = Kind == TTI::SK_Select ? 1 : NumPerms; + return NumPerms + NumPermMasks; + } + + default: + break; } } - // Restore optimal kind. - if (IsExtractSubvector) - Kind = TTI::SK_ExtractSubvector; return BaseT::getShuffleCost(Kind, VT, Mask, CostKind, Index, SubTp); } diff --git a/llvm/test/Analysis/CostModel/AMDGPU/shufflevector.ll b/llvm/test/Analysis/CostModel/AMDGPU/shufflevector.ll index be5cca0765ed..a18156744a36 100644 --- a/llvm/test/Analysis/CostModel/AMDGPU/shufflevector.ll +++ b/llvm/test/Analysis/CostModel/AMDGPU/shufflevector.ll @@ -7,603 +7,1140 @@ ; RUN: opt < %s -passes="print" 2>&1 -disable-output -mtriple=amdgcn-unknown-amdhsa -mcpu=fiji -cost-kind=code-size -S | FileCheck -check-prefixes=ALL-SIZE,VI-SIZE %s ; END. -define amdgpu_kernel void @shufflevector_i16() { +define amdgpu_kernel void @shufflevector_i16(<2 x i16> %vec1, <2 x i16> %vec2) { ; GFX9-10-LABEL: 'shufflevector_i16' -; GFX9-10-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf00 = shufflevector <2 x i16> undef, <2 x i16> undef, <2 x i32> zeroinitializer -; GFX9-10-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf01 = shufflevector <2 x i16> undef, <2 x i16> undef, <2 x i32> -; GFX9-10-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf10 = shufflevector <2 x i16> undef, <2 x i16> undef, <2 x i32> -; GFX9-10-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf11 = shufflevector <2 x i16> undef, <2 x i16> undef, <2 x i32> -; GFX9-10-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %shuf02 = shufflevector <2 x i16> undef, <2 x i16> undef, <2 x i32> -; GFX9-10-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %shuf20 = shufflevector <2 x i16> undef, <2 x i16> undef, <2 x i32> -; GFX9-10-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf22 = shufflevector <2 x i16> undef, <2 x i16> undef, <2 x i32> -; GFX9-10-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %shuf03 = shufflevector <2 x i16> undef, <2 x i16> undef, <2 x i32> -; GFX9-10-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %shuf30 = shufflevector <2 x i16> undef, <2 x i16> undef, <2 x i32> -; GFX9-10-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf33 = shufflevector <2 x i16> undef, <2 x i16> undef, <2 x i32> -; GFX9-10-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %shuf12 = shufflevector <2 x i16> undef, <2 x i16> undef, <2 x i32> -; GFX9-10-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %shuf21 = shufflevector <2 x i16> undef, <2 x i16> undef, <2 x i32> -; GFX9-10-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %shuf13 = shufflevector <2 x i16> undef, <2 x i16> undef, <2 x i32> -; GFX9-10-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %shuf31 = shufflevector <2 x i16> undef, <2 x i16> undef, <2 x i32> -; GFX9-10-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf23 = shufflevector <2 x i16> undef, <2 x i16> undef, <2 x i32> -; GFX9-10-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf32 = shufflevector <2 x i16> undef, <2 x i16> undef, <2 x i32> -; GFX9-10-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %shuf000 = shufflevector <2 x i16> undef, <2 x i16> undef, <3 x i32> zeroinitializer -; GFX9-10-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf001 = shufflevector <2 x i16> undef, <2 x i16> undef, <3 x i32> -; GFX9-10-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf010 = shufflevector <2 x i16> undef, <2 x i16> undef, <3 x i32> -; GFX9-10-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf011 = shufflevector <2 x i16> undef, <2 x i16> undef, <3 x i32> -; GFX9-10-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf100 = shufflevector <2 x i16> undef, <2 x i16> undef, <3 x i32> -; GFX9-10-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf101 = shufflevector <2 x i16> undef, <2 x i16> undef, <3 x i32> -; GFX9-10-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf110 = shufflevector <2 x i16> undef, <2 x i16> undef, <3 x i32> -; GFX9-10-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf111 = shufflevector <2 x i16> undef, <2 x i16> undef, <3 x i32> -; GFX9-10-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf002 = shufflevector <2 x i16> undef, <2 x i16> undef, <3 x i32> -; GFX9-10-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf020 = shufflevector <2 x i16> undef, <2 x i16> undef, <3 x i32> -; GFX9-10-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf022 = shufflevector <2 x i16> undef, <2 x i16> undef, <3 x i32> -; GFX9-10-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf200 = shufflevector <2 x i16> undef, <2 x i16> undef, <3 x i32> -; GFX9-10-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf202 = shufflevector <2 x i16> undef, <2 x i16> undef, <3 x i32> -; GFX9-10-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf220 = shufflevector <2 x i16> undef, <2 x i16> undef, <3 x i32> -; GFX9-10-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %shuf222 = shufflevector <2 x i16> undef, <2 x i16> undef, <3 x i32> -; GFX9-10-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf112 = shufflevector <2 x i16> undef, <2 x i16> undef, <3 x i32> -; GFX9-10-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf121 = shufflevector <2 x i16> undef, <2 x i16> undef, <3 x i32> -; GFX9-10-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf122 = shufflevector <2 x i16> undef, <2 x i16> undef, <3 x i32> -; GFX9-10-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf211 = shufflevector <2 x i16> undef, <2 x i16> undef, <3 x i32> -; GFX9-10-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf212 = shufflevector <2 x i16> undef, <2 x i16> undef, <3 x i32> -; GFX9-10-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf221 = shufflevector <2 x i16> undef, <2 x i16> undef, <3 x i32> +; GFX9-10-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf00 = shufflevector <2 x i16> %vec1, <2 x i16> %vec1, <2 x i32> zeroinitializer +; GFX9-10-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf01 = shufflevector <2 x i16> %vec1, <2 x i16> %vec1, <2 x i32> +; GFX9-10-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf10 = shufflevector <2 x i16> %vec1, <2 x i16> %vec1, <2 x i32> +; GFX9-10-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf11 = shufflevector <2 x i16> %vec1, <2 x i16> %vec1, <2 x i32> +; GFX9-10-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %shuf02 = shufflevector <2 x i16> %vec1, <2 x i16> %vec1, <2 x i32> +; GFX9-10-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %shuf20 = shufflevector <2 x i16> %vec1, <2 x i16> %vec1, <2 x i32> +; GFX9-10-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf22 = shufflevector <2 x i16> %vec1, <2 x i16> %vec1, <2 x i32> +; GFX9-10-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %shuf03 = shufflevector <2 x i16> %vec1, <2 x i16> %vec1, <2 x i32> +; GFX9-10-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %shuf30 = shufflevector <2 x i16> %vec1, <2 x i16> %vec1, <2 x i32> +; GFX9-10-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf33 = shufflevector <2 x i16> %vec1, <2 x i16> %vec1, <2 x i32> +; GFX9-10-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %shuf12 = shufflevector <2 x i16> %vec1, <2 x i16> %vec1, <2 x i32> +; GFX9-10-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %shuf21 = shufflevector <2 x i16> %vec1, <2 x i16> %vec1, <2 x i32> +; GFX9-10-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %shuf13 = shufflevector <2 x i16> %vec1, <2 x i16> %vec1, <2 x i32> +; GFX9-10-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %shuf31 = shufflevector <2 x i16> %vec1, <2 x i16> %vec1, <2 x i32> +; GFX9-10-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf23 = shufflevector <2 x i16> %vec1, <2 x i16> %vec1, <2 x i32> +; GFX9-10-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf32 = shufflevector <2 x i16> %vec1, <2 x i16> %vec1, <2 x i32> +; GFX9-10-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf000 = shufflevector <2 x i16> %vec1, <2 x i16> %vec1, <3 x i32> zeroinitializer +; GFX9-10-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf001 = shufflevector <2 x i16> %vec1, <2 x i16> %vec1, <3 x i32> +; GFX9-10-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf010 = shufflevector <2 x i16> %vec1, <2 x i16> %vec1, <3 x i32> +; GFX9-10-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf011 = shufflevector <2 x i16> %vec1, <2 x i16> %vec1, <3 x i32> +; GFX9-10-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf100 = shufflevector <2 x i16> %vec1, <2 x i16> %vec1, <3 x i32> +; GFX9-10-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf101 = shufflevector <2 x i16> %vec1, <2 x i16> %vec1, <3 x i32> +; GFX9-10-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf110 = shufflevector <2 x i16> %vec1, <2 x i16> %vec1, <3 x i32> +; GFX9-10-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf111 = shufflevector <2 x i16> %vec1, <2 x i16> %vec1, <3 x i32> +; GFX9-10-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf002 = shufflevector <2 x i16> %vec1, <2 x i16> %vec1, <3 x i32> +; GFX9-10-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf020 = shufflevector <2 x i16> %vec1, <2 x i16> %vec1, <3 x i32> +; GFX9-10-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf022 = shufflevector <2 x i16> %vec1, <2 x i16> %vec1, <3 x i32> +; GFX9-10-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf200 = shufflevector <2 x i16> %vec1, <2 x i16> %vec1, <3 x i32> +; GFX9-10-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf202 = shufflevector <2 x i16> %vec1, <2 x i16> %vec1, <3 x i32> +; GFX9-10-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf220 = shufflevector <2 x i16> %vec1, <2 x i16> %vec1, <3 x i32> +; GFX9-10-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf222 = shufflevector <2 x i16> %vec1, <2 x i16> %vec1, <3 x i32> +; GFX9-10-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf112 = shufflevector <2 x i16> %vec1, <2 x i16> %vec1, <3 x i32> +; GFX9-10-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf121 = shufflevector <2 x i16> %vec1, <2 x i16> %vec1, <3 x i32> +; GFX9-10-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf122 = shufflevector <2 x i16> %vec1, <2 x i16> %vec1, <3 x i32> +; GFX9-10-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf211 = shufflevector <2 x i16> %vec1, <2 x i16> %vec1, <3 x i32> +; GFX9-10-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf212 = shufflevector <2 x i16> %vec1, <2 x i16> %vec1, <3 x i32> +; GFX9-10-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf221 = shufflevector <2 x i16> %vec1, <2 x i16> %vec1, <3 x i32> +; GFX9-10-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf00_2 = shufflevector <2 x i16> %vec1, <2 x i16> %vec2, <2 x i32> zeroinitializer +; GFX9-10-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf01_2 = shufflevector <2 x i16> %vec1, <2 x i16> %vec2, <2 x i32> +; GFX9-10-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf10_2 = shufflevector <2 x i16> %vec1, <2 x i16> %vec2, <2 x i32> +; GFX9-10-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf11_2 = shufflevector <2 x i16> %vec1, <2 x i16> %vec2, <2 x i32> +; GFX9-10-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %shuf02_2 = shufflevector <2 x i16> %vec1, <2 x i16> %vec2, <2 x i32> +; GFX9-10-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %shuf20_2 = shufflevector <2 x i16> %vec1, <2 x i16> %vec2, <2 x i32> +; GFX9-10-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf22_2 = shufflevector <2 x i16> %vec1, <2 x i16> %vec2, <2 x i32> +; GFX9-10-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %shuf03_2 = shufflevector <2 x i16> %vec1, <2 x i16> %vec2, <2 x i32> +; GFX9-10-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %shuf30_2 = shufflevector <2 x i16> %vec1, <2 x i16> %vec2, <2 x i32> +; GFX9-10-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf33_2 = shufflevector <2 x i16> %vec1, <2 x i16> %vec2, <2 x i32> +; GFX9-10-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %shuf12_2 = shufflevector <2 x i16> %vec1, <2 x i16> %vec2, <2 x i32> +; GFX9-10-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %shuf21_2 = shufflevector <2 x i16> %vec1, <2 x i16> %vec2, <2 x i32> +; GFX9-10-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %shuf13_2 = shufflevector <2 x i16> %vec1, <2 x i16> %vec2, <2 x i32> +; GFX9-10-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %shuf31_2 = shufflevector <2 x i16> %vec1, <2 x i16> %vec2, <2 x i32> +; GFX9-10-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf23_2 = shufflevector <2 x i16> %vec1, <2 x i16> %vec2, <2 x i32> +; GFX9-10-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf32_2 = shufflevector <2 x i16> %vec1, <2 x i16> %vec2, <2 x i32> +; GFX9-10-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf000_2 = shufflevector <2 x i16> %vec1, <2 x i16> %vec2, <3 x i32> zeroinitializer +; GFX9-10-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf001_2 = shufflevector <2 x i16> %vec1, <2 x i16> %vec2, <3 x i32> +; GFX9-10-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf010_2 = shufflevector <2 x i16> %vec1, <2 x i16> %vec2, <3 x i32> +; GFX9-10-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf011_2 = shufflevector <2 x i16> %vec1, <2 x i16> %vec2, <3 x i32> +; GFX9-10-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf100_2 = shufflevector <2 x i16> %vec1, <2 x i16> %vec2, <3 x i32> +; GFX9-10-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf101_2 = shufflevector <2 x i16> %vec1, <2 x i16> %vec2, <3 x i32> +; GFX9-10-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf110_2 = shufflevector <2 x i16> %vec1, <2 x i16> %vec2, <3 x i32> +; GFX9-10-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf111_2 = shufflevector <2 x i16> %vec1, <2 x i16> %vec2, <3 x i32> +; GFX9-10-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf002_2 = shufflevector <2 x i16> %vec1, <2 x i16> %vec2, <3 x i32> +; GFX9-10-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf020_2 = shufflevector <2 x i16> %vec1, <2 x i16> %vec2, <3 x i32> +; GFX9-10-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf022_2 = shufflevector <2 x i16> %vec1, <2 x i16> %vec2, <3 x i32> +; GFX9-10-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf200_2 = shufflevector <2 x i16> %vec1, <2 x i16> %vec2, <3 x i32> +; GFX9-10-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf202_2 = shufflevector <2 x i16> %vec1, <2 x i16> %vec2, <3 x i32> +; GFX9-10-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf220_2 = shufflevector <2 x i16> %vec1, <2 x i16> %vec2, <3 x i32> +; GFX9-10-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf222_2 = shufflevector <2 x i16> %vec1, <2 x i16> %vec2, <3 x i32> +; GFX9-10-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf112_2 = shufflevector <2 x i16> %vec1, <2 x i16> %vec2, <3 x i32> +; GFX9-10-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf121_2 = shufflevector <2 x i16> %vec1, <2 x i16> %vec2, <3 x i32> +; GFX9-10-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf122_2 = shufflevector <2 x i16> %vec1, <2 x i16> %vec2, <3 x i32> +; GFX9-10-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf211_2 = shufflevector <2 x i16> %vec1, <2 x i16> %vec2, <3 x i32> +; GFX9-10-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf212_2 = shufflevector <2 x i16> %vec1, <2 x i16> %vec2, <3 x i32> +; GFX9-10-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf221_2 = shufflevector <2 x i16> %vec1, <2 x i16> %vec2, <3 x i32> ; GFX9-10-NEXT: Cost Model: Found an estimated cost of 10 for instruction: ret void ; ; VI-LABEL: 'shufflevector_i16' -; VI-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %shuf00 = shufflevector <2 x i16> undef, <2 x i16> undef, <2 x i32> zeroinitializer -; VI-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf01 = shufflevector <2 x i16> undef, <2 x i16> undef, <2 x i32> -; VI-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %shuf10 = shufflevector <2 x i16> undef, <2 x i16> undef, <2 x i32> -; VI-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %shuf11 = shufflevector <2 x i16> undef, <2 x i16> undef, <2 x i32> -; VI-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %shuf02 = shufflevector <2 x i16> undef, <2 x i16> undef, <2 x i32> -; VI-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %shuf20 = shufflevector <2 x i16> undef, <2 x i16> undef, <2 x i32> -; VI-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %shuf22 = shufflevector <2 x i16> undef, <2 x i16> undef, <2 x i32> -; VI-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %shuf03 = shufflevector <2 x i16> undef, <2 x i16> undef, <2 x i32> -; VI-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %shuf30 = shufflevector <2 x i16> undef, <2 x i16> undef, <2 x i32> -; VI-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %shuf33 = shufflevector <2 x i16> undef, <2 x i16> undef, <2 x i32> -; VI-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %shuf12 = shufflevector <2 x i16> undef, <2 x i16> undef, <2 x i32> -; VI-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %shuf21 = shufflevector <2 x i16> undef, <2 x i16> undef, <2 x i32> -; VI-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %shuf13 = shufflevector <2 x i16> undef, <2 x i16> undef, <2 x i32> -; VI-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %shuf31 = shufflevector <2 x i16> undef, <2 x i16> undef, <2 x i32> -; VI-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf23 = shufflevector <2 x i16> undef, <2 x i16> undef, <2 x i32> -; VI-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %shuf32 = shufflevector <2 x i16> undef, <2 x i16> undef, <2 x i32> -; VI-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %shuf000 = shufflevector <2 x i16> undef, <2 x i16> undef, <3 x i32> zeroinitializer -; VI-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf001 = shufflevector <2 x i16> undef, <2 x i16> undef, <3 x i32> -; VI-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf010 = shufflevector <2 x i16> undef, <2 x i16> undef, <3 x i32> -; VI-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf011 = shufflevector <2 x i16> undef, <2 x i16> undef, <3 x i32> -; VI-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf100 = shufflevector <2 x i16> undef, <2 x i16> undef, <3 x i32> -; VI-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf101 = shufflevector <2 x i16> undef, <2 x i16> undef, <3 x i32> -; VI-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf110 = shufflevector <2 x i16> undef, <2 x i16> undef, <3 x i32> -; VI-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf111 = shufflevector <2 x i16> undef, <2 x i16> undef, <3 x i32> -; VI-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf002 = shufflevector <2 x i16> undef, <2 x i16> undef, <3 x i32> -; VI-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf020 = shufflevector <2 x i16> undef, <2 x i16> undef, <3 x i32> -; VI-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf022 = shufflevector <2 x i16> undef, <2 x i16> undef, <3 x i32> -; VI-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf200 = shufflevector <2 x i16> undef, <2 x i16> undef, <3 x i32> -; VI-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf202 = shufflevector <2 x i16> undef, <2 x i16> undef, <3 x i32> -; VI-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf220 = shufflevector <2 x i16> undef, <2 x i16> undef, <3 x i32> -; VI-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %shuf222 = shufflevector <2 x i16> undef, <2 x i16> undef, <3 x i32> -; VI-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf112 = shufflevector <2 x i16> undef, <2 x i16> undef, <3 x i32> -; VI-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf121 = shufflevector <2 x i16> undef, <2 x i16> undef, <3 x i32> -; VI-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf122 = shufflevector <2 x i16> undef, <2 x i16> undef, <3 x i32> -; VI-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf211 = shufflevector <2 x i16> undef, <2 x i16> undef, <3 x i32> -; VI-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf212 = shufflevector <2 x i16> undef, <2 x i16> undef, <3 x i32> -; VI-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf221 = shufflevector <2 x i16> undef, <2 x i16> undef, <3 x i32> +; VI-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %shuf00 = shufflevector <2 x i16> %vec1, <2 x i16> %vec1, <2 x i32> zeroinitializer +; VI-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf01 = shufflevector <2 x i16> %vec1, <2 x i16> %vec1, <2 x i32> +; VI-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %shuf10 = shufflevector <2 x i16> %vec1, <2 x i16> %vec1, <2 x i32> +; VI-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %shuf11 = shufflevector <2 x i16> %vec1, <2 x i16> %vec1, <2 x i32> +; VI-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %shuf02 = shufflevector <2 x i16> %vec1, <2 x i16> %vec1, <2 x i32> +; VI-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %shuf20 = shufflevector <2 x i16> %vec1, <2 x i16> %vec1, <2 x i32> +; VI-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %shuf22 = shufflevector <2 x i16> %vec1, <2 x i16> %vec1, <2 x i32> +; VI-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %shuf03 = shufflevector <2 x i16> %vec1, <2 x i16> %vec1, <2 x i32> +; VI-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %shuf30 = shufflevector <2 x i16> %vec1, <2 x i16> %vec1, <2 x i32> +; VI-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %shuf33 = shufflevector <2 x i16> %vec1, <2 x i16> %vec1, <2 x i32> +; VI-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %shuf12 = shufflevector <2 x i16> %vec1, <2 x i16> %vec1, <2 x i32> +; VI-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %shuf21 = shufflevector <2 x i16> %vec1, <2 x i16> %vec1, <2 x i32> +; VI-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %shuf13 = shufflevector <2 x i16> %vec1, <2 x i16> %vec1, <2 x i32> +; VI-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %shuf31 = shufflevector <2 x i16> %vec1, <2 x i16> %vec1, <2 x i32> +; VI-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf23 = shufflevector <2 x i16> %vec1, <2 x i16> %vec1, <2 x i32> +; VI-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %shuf32 = shufflevector <2 x i16> %vec1, <2 x i16> %vec1, <2 x i32> +; VI-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf000 = shufflevector <2 x i16> %vec1, <2 x i16> %vec1, <3 x i32> zeroinitializer +; VI-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf001 = shufflevector <2 x i16> %vec1, <2 x i16> %vec1, <3 x i32> +; VI-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf010 = shufflevector <2 x i16> %vec1, <2 x i16> %vec1, <3 x i32> +; VI-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf011 = shufflevector <2 x i16> %vec1, <2 x i16> %vec1, <3 x i32> +; VI-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf100 = shufflevector <2 x i16> %vec1, <2 x i16> %vec1, <3 x i32> +; VI-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf101 = shufflevector <2 x i16> %vec1, <2 x i16> %vec1, <3 x i32> +; VI-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf110 = shufflevector <2 x i16> %vec1, <2 x i16> %vec1, <3 x i32> +; VI-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf111 = shufflevector <2 x i16> %vec1, <2 x i16> %vec1, <3 x i32> +; VI-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf002 = shufflevector <2 x i16> %vec1, <2 x i16> %vec1, <3 x i32> +; VI-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf020 = shufflevector <2 x i16> %vec1, <2 x i16> %vec1, <3 x i32> +; VI-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf022 = shufflevector <2 x i16> %vec1, <2 x i16> %vec1, <3 x i32> +; VI-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf200 = shufflevector <2 x i16> %vec1, <2 x i16> %vec1, <3 x i32> +; VI-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf202 = shufflevector <2 x i16> %vec1, <2 x i16> %vec1, <3 x i32> +; VI-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf220 = shufflevector <2 x i16> %vec1, <2 x i16> %vec1, <3 x i32> +; VI-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf222 = shufflevector <2 x i16> %vec1, <2 x i16> %vec1, <3 x i32> +; VI-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf112 = shufflevector <2 x i16> %vec1, <2 x i16> %vec1, <3 x i32> +; VI-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf121 = shufflevector <2 x i16> %vec1, <2 x i16> %vec1, <3 x i32> +; VI-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf122 = shufflevector <2 x i16> %vec1, <2 x i16> %vec1, <3 x i32> +; VI-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf211 = shufflevector <2 x i16> %vec1, <2 x i16> %vec1, <3 x i32> +; VI-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf212 = shufflevector <2 x i16> %vec1, <2 x i16> %vec1, <3 x i32> +; VI-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf221 = shufflevector <2 x i16> %vec1, <2 x i16> %vec1, <3 x i32> +; VI-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %shuf00_2 = shufflevector <2 x i16> %vec1, <2 x i16> %vec2, <2 x i32> zeroinitializer +; VI-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf01_2 = shufflevector <2 x i16> %vec1, <2 x i16> %vec2, <2 x i32> +; VI-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %shuf10_2 = shufflevector <2 x i16> %vec1, <2 x i16> %vec2, <2 x i32> +; VI-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %shuf11_2 = shufflevector <2 x i16> %vec1, <2 x i16> %vec2, <2 x i32> +; VI-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %shuf02_2 = shufflevector <2 x i16> %vec1, <2 x i16> %vec2, <2 x i32> +; VI-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %shuf20_2 = shufflevector <2 x i16> %vec1, <2 x i16> %vec2, <2 x i32> +; VI-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %shuf22_2 = shufflevector <2 x i16> %vec1, <2 x i16> %vec2, <2 x i32> +; VI-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %shuf03_2 = shufflevector <2 x i16> %vec1, <2 x i16> %vec2, <2 x i32> +; VI-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %shuf30_2 = shufflevector <2 x i16> %vec1, <2 x i16> %vec2, <2 x i32> +; VI-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %shuf33_2 = shufflevector <2 x i16> %vec1, <2 x i16> %vec2, <2 x i32> +; VI-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %shuf12_2 = shufflevector <2 x i16> %vec1, <2 x i16> %vec2, <2 x i32> +; VI-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %shuf21_2 = shufflevector <2 x i16> %vec1, <2 x i16> %vec2, <2 x i32> +; VI-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %shuf13_2 = shufflevector <2 x i16> %vec1, <2 x i16> %vec2, <2 x i32> +; VI-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %shuf31_2 = shufflevector <2 x i16> %vec1, <2 x i16> %vec2, <2 x i32> +; VI-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf23_2 = shufflevector <2 x i16> %vec1, <2 x i16> %vec2, <2 x i32> +; VI-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %shuf32_2 = shufflevector <2 x i16> %vec1, <2 x i16> %vec2, <2 x i32> +; VI-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf000_2 = shufflevector <2 x i16> %vec1, <2 x i16> %vec2, <3 x i32> zeroinitializer +; VI-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf001_2 = shufflevector <2 x i16> %vec1, <2 x i16> %vec2, <3 x i32> +; VI-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf010_2 = shufflevector <2 x i16> %vec1, <2 x i16> %vec2, <3 x i32> +; VI-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf011_2 = shufflevector <2 x i16> %vec1, <2 x i16> %vec2, <3 x i32> +; VI-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf100_2 = shufflevector <2 x i16> %vec1, <2 x i16> %vec2, <3 x i32> +; VI-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf101_2 = shufflevector <2 x i16> %vec1, <2 x i16> %vec2, <3 x i32> +; VI-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf110_2 = shufflevector <2 x i16> %vec1, <2 x i16> %vec2, <3 x i32> +; VI-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf111_2 = shufflevector <2 x i16> %vec1, <2 x i16> %vec2, <3 x i32> +; VI-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf002_2 = shufflevector <2 x i16> %vec1, <2 x i16> %vec2, <3 x i32> +; VI-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf020_2 = shufflevector <2 x i16> %vec1, <2 x i16> %vec2, <3 x i32> +; VI-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf022_2 = shufflevector <2 x i16> %vec1, <2 x i16> %vec2, <3 x i32> +; VI-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf200_2 = shufflevector <2 x i16> %vec1, <2 x i16> %vec2, <3 x i32> +; VI-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf202_2 = shufflevector <2 x i16> %vec1, <2 x i16> %vec2, <3 x i32> +; VI-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf220_2 = shufflevector <2 x i16> %vec1, <2 x i16> %vec2, <3 x i32> +; VI-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf222_2 = shufflevector <2 x i16> %vec1, <2 x i16> %vec2, <3 x i32> +; VI-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf112_2 = shufflevector <2 x i16> %vec1, <2 x i16> %vec2, <3 x i32> +; VI-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf121_2 = shufflevector <2 x i16> %vec1, <2 x i16> %vec2, <3 x i32> +; VI-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf122_2 = shufflevector <2 x i16> %vec1, <2 x i16> %vec2, <3 x i32> +; VI-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf211_2 = shufflevector <2 x i16> %vec1, <2 x i16> %vec2, <3 x i32> +; VI-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf212_2 = shufflevector <2 x i16> %vec1, <2 x i16> %vec2, <3 x i32> +; VI-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf221_2 = shufflevector <2 x i16> %vec1, <2 x i16> %vec2, <3 x i32> ; VI-NEXT: Cost Model: Found an estimated cost of 10 for instruction: ret void ; ; GFX9-10-SIZE-LABEL: 'shufflevector_i16' -; GFX9-10-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf00 = shufflevector <2 x i16> undef, <2 x i16> undef, <2 x i32> zeroinitializer -; GFX9-10-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf01 = shufflevector <2 x i16> undef, <2 x i16> undef, <2 x i32> -; GFX9-10-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf10 = shufflevector <2 x i16> undef, <2 x i16> undef, <2 x i32> -; GFX9-10-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf11 = shufflevector <2 x i16> undef, <2 x i16> undef, <2 x i32> -; GFX9-10-SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %shuf02 = shufflevector <2 x i16> undef, <2 x i16> undef, <2 x i32> -; GFX9-10-SIZE-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %shuf20 = shufflevector <2 x i16> undef, <2 x i16> undef, <2 x i32> -; GFX9-10-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf22 = shufflevector <2 x i16> undef, <2 x i16> undef, <2 x i32> -; GFX9-10-SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %shuf03 = shufflevector <2 x i16> undef, <2 x i16> undef, <2 x i32> -; GFX9-10-SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %shuf30 = shufflevector <2 x i16> undef, <2 x i16> undef, <2 x i32> -; GFX9-10-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf33 = shufflevector <2 x i16> undef, <2 x i16> undef, <2 x i32> -; GFX9-10-SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %shuf12 = shufflevector <2 x i16> undef, <2 x i16> undef, <2 x i32> -; GFX9-10-SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %shuf21 = shufflevector <2 x i16> undef, <2 x i16> undef, <2 x i32> -; GFX9-10-SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %shuf13 = shufflevector <2 x i16> undef, <2 x i16> undef, <2 x i32> -; GFX9-10-SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %shuf31 = shufflevector <2 x i16> undef, <2 x i16> undef, <2 x i32> -; GFX9-10-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf23 = shufflevector <2 x i16> undef, <2 x i16> undef, <2 x i32> -; GFX9-10-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf32 = shufflevector <2 x i16> undef, <2 x i16> undef, <2 x i32> -; GFX9-10-SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %shuf000 = shufflevector <2 x i16> undef, <2 x i16> undef, <3 x i32> zeroinitializer -; GFX9-10-SIZE-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf001 = shufflevector <2 x i16> undef, <2 x i16> undef, <3 x i32> -; GFX9-10-SIZE-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf010 = shufflevector <2 x i16> undef, <2 x i16> undef, <3 x i32> -; GFX9-10-SIZE-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf011 = shufflevector <2 x i16> undef, <2 x i16> undef, <3 x i32> -; GFX9-10-SIZE-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf100 = shufflevector <2 x i16> undef, <2 x i16> undef, <3 x i32> -; GFX9-10-SIZE-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf101 = shufflevector <2 x i16> undef, <2 x i16> undef, <3 x i32> -; GFX9-10-SIZE-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf110 = shufflevector <2 x i16> undef, <2 x i16> undef, <3 x i32> -; GFX9-10-SIZE-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf111 = shufflevector <2 x i16> undef, <2 x i16> undef, <3 x i32> -; GFX9-10-SIZE-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf002 = shufflevector <2 x i16> undef, <2 x i16> undef, <3 x i32> -; GFX9-10-SIZE-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf020 = shufflevector <2 x i16> undef, <2 x i16> undef, <3 x i32> -; GFX9-10-SIZE-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf022 = shufflevector <2 x i16> undef, <2 x i16> undef, <3 x i32> -; GFX9-10-SIZE-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf200 = shufflevector <2 x i16> undef, <2 x i16> undef, <3 x i32> -; GFX9-10-SIZE-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf202 = shufflevector <2 x i16> undef, <2 x i16> undef, <3 x i32> -; GFX9-10-SIZE-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf220 = shufflevector <2 x i16> undef, <2 x i16> undef, <3 x i32> -; GFX9-10-SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %shuf222 = shufflevector <2 x i16> undef, <2 x i16> undef, <3 x i32> -; GFX9-10-SIZE-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf112 = shufflevector <2 x i16> undef, <2 x i16> undef, <3 x i32> -; GFX9-10-SIZE-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf121 = shufflevector <2 x i16> undef, <2 x i16> undef, <3 x i32> -; GFX9-10-SIZE-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf122 = shufflevector <2 x i16> undef, <2 x i16> undef, <3 x i32> -; GFX9-10-SIZE-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf211 = shufflevector <2 x i16> undef, <2 x i16> undef, <3 x i32> -; GFX9-10-SIZE-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf212 = shufflevector <2 x i16> undef, <2 x i16> undef, <3 x i32> -; GFX9-10-SIZE-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf221 = shufflevector <2 x i16> undef, <2 x i16> undef, <3 x i32> +; GFX9-10-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf00 = shufflevector <2 x i16> %vec1, <2 x i16> %vec1, <2 x i32> zeroinitializer +; GFX9-10-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf01 = shufflevector <2 x i16> %vec1, <2 x i16> %vec1, <2 x i32> +; GFX9-10-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf10 = shufflevector <2 x i16> %vec1, <2 x i16> %vec1, <2 x i32> +; GFX9-10-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf11 = shufflevector <2 x i16> %vec1, <2 x i16> %vec1, <2 x i32> +; GFX9-10-SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %shuf02 = shufflevector <2 x i16> %vec1, <2 x i16> %vec1, <2 x i32> +; GFX9-10-SIZE-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %shuf20 = shufflevector <2 x i16> %vec1, <2 x i16> %vec1, <2 x i32> +; GFX9-10-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf22 = shufflevector <2 x i16> %vec1, <2 x i16> %vec1, <2 x i32> +; GFX9-10-SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %shuf03 = shufflevector <2 x i16> %vec1, <2 x i16> %vec1, <2 x i32> +; GFX9-10-SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %shuf30 = shufflevector <2 x i16> %vec1, <2 x i16> %vec1, <2 x i32> +; GFX9-10-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf33 = shufflevector <2 x i16> %vec1, <2 x i16> %vec1, <2 x i32> +; GFX9-10-SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %shuf12 = shufflevector <2 x i16> %vec1, <2 x i16> %vec1, <2 x i32> +; GFX9-10-SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %shuf21 = shufflevector <2 x i16> %vec1, <2 x i16> %vec1, <2 x i32> +; GFX9-10-SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %shuf13 = shufflevector <2 x i16> %vec1, <2 x i16> %vec1, <2 x i32> +; GFX9-10-SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %shuf31 = shufflevector <2 x i16> %vec1, <2 x i16> %vec1, <2 x i32> +; GFX9-10-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf23 = shufflevector <2 x i16> %vec1, <2 x i16> %vec1, <2 x i32> +; GFX9-10-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf32 = shufflevector <2 x i16> %vec1, <2 x i16> %vec1, <2 x i32> +; GFX9-10-SIZE-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf000 = shufflevector <2 x i16> %vec1, <2 x i16> %vec1, <3 x i32> zeroinitializer +; GFX9-10-SIZE-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf001 = shufflevector <2 x i16> %vec1, <2 x i16> %vec1, <3 x i32> +; GFX9-10-SIZE-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf010 = shufflevector <2 x i16> %vec1, <2 x i16> %vec1, <3 x i32> +; GFX9-10-SIZE-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf011 = shufflevector <2 x i16> %vec1, <2 x i16> %vec1, <3 x i32> +; GFX9-10-SIZE-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf100 = shufflevector <2 x i16> %vec1, <2 x i16> %vec1, <3 x i32> +; GFX9-10-SIZE-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf101 = shufflevector <2 x i16> %vec1, <2 x i16> %vec1, <3 x i32> +; GFX9-10-SIZE-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf110 = shufflevector <2 x i16> %vec1, <2 x i16> %vec1, <3 x i32> +; GFX9-10-SIZE-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf111 = shufflevector <2 x i16> %vec1, <2 x i16> %vec1, <3 x i32> +; GFX9-10-SIZE-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf002 = shufflevector <2 x i16> %vec1, <2 x i16> %vec1, <3 x i32> +; GFX9-10-SIZE-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf020 = shufflevector <2 x i16> %vec1, <2 x i16> %vec1, <3 x i32> +; GFX9-10-SIZE-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf022 = shufflevector <2 x i16> %vec1, <2 x i16> %vec1, <3 x i32> +; GFX9-10-SIZE-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf200 = shufflevector <2 x i16> %vec1, <2 x i16> %vec1, <3 x i32> +; GFX9-10-SIZE-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf202 = shufflevector <2 x i16> %vec1, <2 x i16> %vec1, <3 x i32> +; GFX9-10-SIZE-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf220 = shufflevector <2 x i16> %vec1, <2 x i16> %vec1, <3 x i32> +; GFX9-10-SIZE-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf222 = shufflevector <2 x i16> %vec1, <2 x i16> %vec1, <3 x i32> +; GFX9-10-SIZE-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf112 = shufflevector <2 x i16> %vec1, <2 x i16> %vec1, <3 x i32> +; GFX9-10-SIZE-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf121 = shufflevector <2 x i16> %vec1, <2 x i16> %vec1, <3 x i32> +; GFX9-10-SIZE-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf122 = shufflevector <2 x i16> %vec1, <2 x i16> %vec1, <3 x i32> +; GFX9-10-SIZE-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf211 = shufflevector <2 x i16> %vec1, <2 x i16> %vec1, <3 x i32> +; GFX9-10-SIZE-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf212 = shufflevector <2 x i16> %vec1, <2 x i16> %vec1, <3 x i32> +; GFX9-10-SIZE-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf221 = shufflevector <2 x i16> %vec1, <2 x i16> %vec1, <3 x i32> +; GFX9-10-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf00_2 = shufflevector <2 x i16> %vec1, <2 x i16> %vec2, <2 x i32> zeroinitializer +; GFX9-10-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf01_2 = shufflevector <2 x i16> %vec1, <2 x i16> %vec2, <2 x i32> +; GFX9-10-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf10_2 = shufflevector <2 x i16> %vec1, <2 x i16> %vec2, <2 x i32> +; GFX9-10-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf11_2 = shufflevector <2 x i16> %vec1, <2 x i16> %vec2, <2 x i32> +; GFX9-10-SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %shuf02_2 = shufflevector <2 x i16> %vec1, <2 x i16> %vec2, <2 x i32> +; GFX9-10-SIZE-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %shuf20_2 = shufflevector <2 x i16> %vec1, <2 x i16> %vec2, <2 x i32> +; GFX9-10-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf22_2 = shufflevector <2 x i16> %vec1, <2 x i16> %vec2, <2 x i32> +; GFX9-10-SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %shuf03_2 = shufflevector <2 x i16> %vec1, <2 x i16> %vec2, <2 x i32> +; GFX9-10-SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %shuf30_2 = shufflevector <2 x i16> %vec1, <2 x i16> %vec2, <2 x i32> +; GFX9-10-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf33_2 = shufflevector <2 x i16> %vec1, <2 x i16> %vec2, <2 x i32> +; GFX9-10-SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %shuf12_2 = shufflevector <2 x i16> %vec1, <2 x i16> %vec2, <2 x i32> +; GFX9-10-SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %shuf21_2 = shufflevector <2 x i16> %vec1, <2 x i16> %vec2, <2 x i32> +; GFX9-10-SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %shuf13_2 = shufflevector <2 x i16> %vec1, <2 x i16> %vec2, <2 x i32> +; GFX9-10-SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %shuf31_2 = shufflevector <2 x i16> %vec1, <2 x i16> %vec2, <2 x i32> +; GFX9-10-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf23_2 = shufflevector <2 x i16> %vec1, <2 x i16> %vec2, <2 x i32> +; GFX9-10-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf32_2 = shufflevector <2 x i16> %vec1, <2 x i16> %vec2, <2 x i32> +; GFX9-10-SIZE-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf000_2 = shufflevector <2 x i16> %vec1, <2 x i16> %vec2, <3 x i32> zeroinitializer +; GFX9-10-SIZE-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf001_2 = shufflevector <2 x i16> %vec1, <2 x i16> %vec2, <3 x i32> +; GFX9-10-SIZE-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf010_2 = shufflevector <2 x i16> %vec1, <2 x i16> %vec2, <3 x i32> +; GFX9-10-SIZE-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf011_2 = shufflevector <2 x i16> %vec1, <2 x i16> %vec2, <3 x i32> +; GFX9-10-SIZE-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf100_2 = shufflevector <2 x i16> %vec1, <2 x i16> %vec2, <3 x i32> +; GFX9-10-SIZE-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf101_2 = shufflevector <2 x i16> %vec1, <2 x i16> %vec2, <3 x i32> +; GFX9-10-SIZE-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf110_2 = shufflevector <2 x i16> %vec1, <2 x i16> %vec2, <3 x i32> +; GFX9-10-SIZE-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf111_2 = shufflevector <2 x i16> %vec1, <2 x i16> %vec2, <3 x i32> +; GFX9-10-SIZE-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf002_2 = shufflevector <2 x i16> %vec1, <2 x i16> %vec2, <3 x i32> +; GFX9-10-SIZE-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf020_2 = shufflevector <2 x i16> %vec1, <2 x i16> %vec2, <3 x i32> +; GFX9-10-SIZE-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf022_2 = shufflevector <2 x i16> %vec1, <2 x i16> %vec2, <3 x i32> +; GFX9-10-SIZE-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf200_2 = shufflevector <2 x i16> %vec1, <2 x i16> %vec2, <3 x i32> +; GFX9-10-SIZE-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf202_2 = shufflevector <2 x i16> %vec1, <2 x i16> %vec2, <3 x i32> +; GFX9-10-SIZE-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf220_2 = shufflevector <2 x i16> %vec1, <2 x i16> %vec2, <3 x i32> +; GFX9-10-SIZE-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf222_2 = shufflevector <2 x i16> %vec1, <2 x i16> %vec2, <3 x i32> +; GFX9-10-SIZE-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf112_2 = shufflevector <2 x i16> %vec1, <2 x i16> %vec2, <3 x i32> +; GFX9-10-SIZE-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf121_2 = shufflevector <2 x i16> %vec1, <2 x i16> %vec2, <3 x i32> +; GFX9-10-SIZE-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf122_2 = shufflevector <2 x i16> %vec1, <2 x i16> %vec2, <3 x i32> +; GFX9-10-SIZE-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf211_2 = shufflevector <2 x i16> %vec1, <2 x i16> %vec2, <3 x i32> +; GFX9-10-SIZE-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf212_2 = shufflevector <2 x i16> %vec1, <2 x i16> %vec2, <3 x i32> +; GFX9-10-SIZE-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf221_2 = shufflevector <2 x i16> %vec1, <2 x i16> %vec2, <3 x i32> ; GFX9-10-SIZE-NEXT: Cost Model: Found an estimated cost of 1 for instruction: ret void ; ; VI-SIZE-LABEL: 'shufflevector_i16' -; VI-SIZE-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %shuf00 = shufflevector <2 x i16> undef, <2 x i16> undef, <2 x i32> zeroinitializer -; VI-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf01 = shufflevector <2 x i16> undef, <2 x i16> undef, <2 x i32> -; VI-SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %shuf10 = shufflevector <2 x i16> undef, <2 x i16> undef, <2 x i32> -; VI-SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %shuf11 = shufflevector <2 x i16> undef, <2 x i16> undef, <2 x i32> -; VI-SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %shuf02 = shufflevector <2 x i16> undef, <2 x i16> undef, <2 x i32> -; VI-SIZE-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %shuf20 = shufflevector <2 x i16> undef, <2 x i16> undef, <2 x i32> -; VI-SIZE-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %shuf22 = shufflevector <2 x i16> undef, <2 x i16> undef, <2 x i32> -; VI-SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %shuf03 = shufflevector <2 x i16> undef, <2 x i16> undef, <2 x i32> -; VI-SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %shuf30 = shufflevector <2 x i16> undef, <2 x i16> undef, <2 x i32> -; VI-SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %shuf33 = shufflevector <2 x i16> undef, <2 x i16> undef, <2 x i32> -; VI-SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %shuf12 = shufflevector <2 x i16> undef, <2 x i16> undef, <2 x i32> -; VI-SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %shuf21 = shufflevector <2 x i16> undef, <2 x i16> undef, <2 x i32> -; VI-SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %shuf13 = shufflevector <2 x i16> undef, <2 x i16> undef, <2 x i32> -; VI-SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %shuf31 = shufflevector <2 x i16> undef, <2 x i16> undef, <2 x i32> -; VI-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf23 = shufflevector <2 x i16> undef, <2 x i16> undef, <2 x i32> -; VI-SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %shuf32 = shufflevector <2 x i16> undef, <2 x i16> undef, <2 x i32> -; VI-SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %shuf000 = shufflevector <2 x i16> undef, <2 x i16> undef, <3 x i32> zeroinitializer -; VI-SIZE-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf001 = shufflevector <2 x i16> undef, <2 x i16> undef, <3 x i32> -; VI-SIZE-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf010 = shufflevector <2 x i16> undef, <2 x i16> undef, <3 x i32> -; VI-SIZE-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf011 = shufflevector <2 x i16> undef, <2 x i16> undef, <3 x i32> -; VI-SIZE-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf100 = shufflevector <2 x i16> undef, <2 x i16> undef, <3 x i32> -; VI-SIZE-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf101 = shufflevector <2 x i16> undef, <2 x i16> undef, <3 x i32> -; VI-SIZE-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf110 = shufflevector <2 x i16> undef, <2 x i16> undef, <3 x i32> -; VI-SIZE-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf111 = shufflevector <2 x i16> undef, <2 x i16> undef, <3 x i32> -; VI-SIZE-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf002 = shufflevector <2 x i16> undef, <2 x i16> undef, <3 x i32> -; VI-SIZE-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf020 = shufflevector <2 x i16> undef, <2 x i16> undef, <3 x i32> -; VI-SIZE-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf022 = shufflevector <2 x i16> undef, <2 x i16> undef, <3 x i32> -; VI-SIZE-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf200 = shufflevector <2 x i16> undef, <2 x i16> undef, <3 x i32> -; VI-SIZE-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf202 = shufflevector <2 x i16> undef, <2 x i16> undef, <3 x i32> -; VI-SIZE-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf220 = shufflevector <2 x i16> undef, <2 x i16> undef, <3 x i32> -; VI-SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %shuf222 = shufflevector <2 x i16> undef, <2 x i16> undef, <3 x i32> -; VI-SIZE-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf112 = shufflevector <2 x i16> undef, <2 x i16> undef, <3 x i32> -; VI-SIZE-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf121 = shufflevector <2 x i16> undef, <2 x i16> undef, <3 x i32> -; VI-SIZE-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf122 = shufflevector <2 x i16> undef, <2 x i16> undef, <3 x i32> -; VI-SIZE-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf211 = shufflevector <2 x i16> undef, <2 x i16> undef, <3 x i32> -; VI-SIZE-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf212 = shufflevector <2 x i16> undef, <2 x i16> undef, <3 x i32> -; VI-SIZE-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf221 = shufflevector <2 x i16> undef, <2 x i16> undef, <3 x i32> +; VI-SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %shuf00 = shufflevector <2 x i16> %vec1, <2 x i16> %vec1, <2 x i32> zeroinitializer +; VI-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf01 = shufflevector <2 x i16> %vec1, <2 x i16> %vec1, <2 x i32> +; VI-SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %shuf10 = shufflevector <2 x i16> %vec1, <2 x i16> %vec1, <2 x i32> +; VI-SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %shuf11 = shufflevector <2 x i16> %vec1, <2 x i16> %vec1, <2 x i32> +; VI-SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %shuf02 = shufflevector <2 x i16> %vec1, <2 x i16> %vec1, <2 x i32> +; VI-SIZE-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %shuf20 = shufflevector <2 x i16> %vec1, <2 x i16> %vec1, <2 x i32> +; VI-SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %shuf22 = shufflevector <2 x i16> %vec1, <2 x i16> %vec1, <2 x i32> +; VI-SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %shuf03 = shufflevector <2 x i16> %vec1, <2 x i16> %vec1, <2 x i32> +; VI-SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %shuf30 = shufflevector <2 x i16> %vec1, <2 x i16> %vec1, <2 x i32> +; VI-SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %shuf33 = shufflevector <2 x i16> %vec1, <2 x i16> %vec1, <2 x i32> +; VI-SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %shuf12 = shufflevector <2 x i16> %vec1, <2 x i16> %vec1, <2 x i32> +; VI-SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %shuf21 = shufflevector <2 x i16> %vec1, <2 x i16> %vec1, <2 x i32> +; VI-SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %shuf13 = shufflevector <2 x i16> %vec1, <2 x i16> %vec1, <2 x i32> +; VI-SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %shuf31 = shufflevector <2 x i16> %vec1, <2 x i16> %vec1, <2 x i32> +; VI-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf23 = shufflevector <2 x i16> %vec1, <2 x i16> %vec1, <2 x i32> +; VI-SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %shuf32 = shufflevector <2 x i16> %vec1, <2 x i16> %vec1, <2 x i32> +; VI-SIZE-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf000 = shufflevector <2 x i16> %vec1, <2 x i16> %vec1, <3 x i32> zeroinitializer +; VI-SIZE-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf001 = shufflevector <2 x i16> %vec1, <2 x i16> %vec1, <3 x i32> +; VI-SIZE-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf010 = shufflevector <2 x i16> %vec1, <2 x i16> %vec1, <3 x i32> +; VI-SIZE-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf011 = shufflevector <2 x i16> %vec1, <2 x i16> %vec1, <3 x i32> +; VI-SIZE-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf100 = shufflevector <2 x i16> %vec1, <2 x i16> %vec1, <3 x i32> +; VI-SIZE-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf101 = shufflevector <2 x i16> %vec1, <2 x i16> %vec1, <3 x i32> +; VI-SIZE-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf110 = shufflevector <2 x i16> %vec1, <2 x i16> %vec1, <3 x i32> +; VI-SIZE-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf111 = shufflevector <2 x i16> %vec1, <2 x i16> %vec1, <3 x i32> +; VI-SIZE-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf002 = shufflevector <2 x i16> %vec1, <2 x i16> %vec1, <3 x i32> +; VI-SIZE-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf020 = shufflevector <2 x i16> %vec1, <2 x i16> %vec1, <3 x i32> +; VI-SIZE-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf022 = shufflevector <2 x i16> %vec1, <2 x i16> %vec1, <3 x i32> +; VI-SIZE-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf200 = shufflevector <2 x i16> %vec1, <2 x i16> %vec1, <3 x i32> +; VI-SIZE-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf202 = shufflevector <2 x i16> %vec1, <2 x i16> %vec1, <3 x i32> +; VI-SIZE-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf220 = shufflevector <2 x i16> %vec1, <2 x i16> %vec1, <3 x i32> +; VI-SIZE-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf222 = shufflevector <2 x i16> %vec1, <2 x i16> %vec1, <3 x i32> +; VI-SIZE-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf112 = shufflevector <2 x i16> %vec1, <2 x i16> %vec1, <3 x i32> +; VI-SIZE-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf121 = shufflevector <2 x i16> %vec1, <2 x i16> %vec1, <3 x i32> +; VI-SIZE-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf122 = shufflevector <2 x i16> %vec1, <2 x i16> %vec1, <3 x i32> +; VI-SIZE-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf211 = shufflevector <2 x i16> %vec1, <2 x i16> %vec1, <3 x i32> +; VI-SIZE-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf212 = shufflevector <2 x i16> %vec1, <2 x i16> %vec1, <3 x i32> +; VI-SIZE-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf221 = shufflevector <2 x i16> %vec1, <2 x i16> %vec1, <3 x i32> +; VI-SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %shuf00_2 = shufflevector <2 x i16> %vec1, <2 x i16> %vec2, <2 x i32> zeroinitializer +; VI-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf01_2 = shufflevector <2 x i16> %vec1, <2 x i16> %vec2, <2 x i32> +; VI-SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %shuf10_2 = shufflevector <2 x i16> %vec1, <2 x i16> %vec2, <2 x i32> +; VI-SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %shuf11_2 = shufflevector <2 x i16> %vec1, <2 x i16> %vec2, <2 x i32> +; VI-SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %shuf02_2 = shufflevector <2 x i16> %vec1, <2 x i16> %vec2, <2 x i32> +; VI-SIZE-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %shuf20_2 = shufflevector <2 x i16> %vec1, <2 x i16> %vec2, <2 x i32> +; VI-SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %shuf22_2 = shufflevector <2 x i16> %vec1, <2 x i16> %vec2, <2 x i32> +; VI-SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %shuf03_2 = shufflevector <2 x i16> %vec1, <2 x i16> %vec2, <2 x i32> +; VI-SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %shuf30_2 = shufflevector <2 x i16> %vec1, <2 x i16> %vec2, <2 x i32> +; VI-SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %shuf33_2 = shufflevector <2 x i16> %vec1, <2 x i16> %vec2, <2 x i32> +; VI-SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %shuf12_2 = shufflevector <2 x i16> %vec1, <2 x i16> %vec2, <2 x i32> +; VI-SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %shuf21_2 = shufflevector <2 x i16> %vec1, <2 x i16> %vec2, <2 x i32> +; VI-SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %shuf13_2 = shufflevector <2 x i16> %vec1, <2 x i16> %vec2, <2 x i32> +; VI-SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %shuf31_2 = shufflevector <2 x i16> %vec1, <2 x i16> %vec2, <2 x i32> +; VI-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf23_2 = shufflevector <2 x i16> %vec1, <2 x i16> %vec2, <2 x i32> +; VI-SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %shuf32_2 = shufflevector <2 x i16> %vec1, <2 x i16> %vec2, <2 x i32> +; VI-SIZE-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf000_2 = shufflevector <2 x i16> %vec1, <2 x i16> %vec2, <3 x i32> zeroinitializer +; VI-SIZE-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf001_2 = shufflevector <2 x i16> %vec1, <2 x i16> %vec2, <3 x i32> +; VI-SIZE-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf010_2 = shufflevector <2 x i16> %vec1, <2 x i16> %vec2, <3 x i32> +; VI-SIZE-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf011_2 = shufflevector <2 x i16> %vec1, <2 x i16> %vec2, <3 x i32> +; VI-SIZE-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf100_2 = shufflevector <2 x i16> %vec1, <2 x i16> %vec2, <3 x i32> +; VI-SIZE-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf101_2 = shufflevector <2 x i16> %vec1, <2 x i16> %vec2, <3 x i32> +; VI-SIZE-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf110_2 = shufflevector <2 x i16> %vec1, <2 x i16> %vec2, <3 x i32> +; VI-SIZE-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf111_2 = shufflevector <2 x i16> %vec1, <2 x i16> %vec2, <3 x i32> +; VI-SIZE-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf002_2 = shufflevector <2 x i16> %vec1, <2 x i16> %vec2, <3 x i32> +; VI-SIZE-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf020_2 = shufflevector <2 x i16> %vec1, <2 x i16> %vec2, <3 x i32> +; VI-SIZE-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf022_2 = shufflevector <2 x i16> %vec1, <2 x i16> %vec2, <3 x i32> +; VI-SIZE-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf200_2 = shufflevector <2 x i16> %vec1, <2 x i16> %vec2, <3 x i32> +; VI-SIZE-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf202_2 = shufflevector <2 x i16> %vec1, <2 x i16> %vec2, <3 x i32> +; VI-SIZE-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf220_2 = shufflevector <2 x i16> %vec1, <2 x i16> %vec2, <3 x i32> +; VI-SIZE-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf222_2 = shufflevector <2 x i16> %vec1, <2 x i16> %vec2, <3 x i32> +; VI-SIZE-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf112_2 = shufflevector <2 x i16> %vec1, <2 x i16> %vec2, <3 x i32> +; VI-SIZE-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf121_2 = shufflevector <2 x i16> %vec1, <2 x i16> %vec2, <3 x i32> +; VI-SIZE-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf122_2 = shufflevector <2 x i16> %vec1, <2 x i16> %vec2, <3 x i32> +; VI-SIZE-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf211_2 = shufflevector <2 x i16> %vec1, <2 x i16> %vec2, <3 x i32> +; VI-SIZE-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf212_2 = shufflevector <2 x i16> %vec1, <2 x i16> %vec2, <3 x i32> +; VI-SIZE-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf221_2 = shufflevector <2 x i16> %vec1, <2 x i16> %vec2, <3 x i32> ; VI-SIZE-NEXT: Cost Model: Found an estimated cost of 1 for instruction: ret void ; - %shuf00 = shufflevector <2 x i16> undef, <2 x i16> undef, <2 x i32> zeroinitializer - %shuf01 = shufflevector <2 x i16> undef, <2 x i16> undef, <2 x i32> - %shuf10 = shufflevector <2 x i16> undef, <2 x i16> undef, <2 x i32> - %shuf11 = shufflevector <2 x i16> undef, <2 x i16> undef, <2 x i32> - %shuf02 = shufflevector <2 x i16> undef, <2 x i16> undef, <2 x i32> - %shuf20 = shufflevector <2 x i16> undef, <2 x i16> undef, <2 x i32> - %shuf22 = shufflevector <2 x i16> undef, <2 x i16> undef, <2 x i32> - %shuf03 = shufflevector <2 x i16> undef, <2 x i16> undef, <2 x i32> - %shuf30 = shufflevector <2 x i16> undef, <2 x i16> undef, <2 x i32> - %shuf33 = shufflevector <2 x i16> undef, <2 x i16> undef, <2 x i32> - %shuf12 = shufflevector <2 x i16> undef, <2 x i16> undef, <2 x i32> - %shuf21 = shufflevector <2 x i16> undef, <2 x i16> undef, <2 x i32> - %shuf13 = shufflevector <2 x i16> undef, <2 x i16> undef, <2 x i32> - %shuf31 = shufflevector <2 x i16> undef, <2 x i16> undef, <2 x i32> - %shuf23 = shufflevector <2 x i16> undef, <2 x i16> undef, <2 x i32> - %shuf32 = shufflevector <2 x i16> undef, <2 x i16> undef, <2 x i32> - %shuf000 = shufflevector <2 x i16> undef, <2 x i16> undef, <3 x i32> - %shuf001 = shufflevector <2 x i16> undef, <2 x i16> undef, <3 x i32> - %shuf010 = shufflevector <2 x i16> undef, <2 x i16> undef, <3 x i32> - %shuf011 = shufflevector <2 x i16> undef, <2 x i16> undef, <3 x i32> - %shuf100 = shufflevector <2 x i16> undef, <2 x i16> undef, <3 x i32> - %shuf101 = shufflevector <2 x i16> undef, <2 x i16> undef, <3 x i32> - %shuf110 = shufflevector <2 x i16> undef, <2 x i16> undef, <3 x i32> - %shuf111 = shufflevector <2 x i16> undef, <2 x i16> undef, <3 x i32> - %shuf002 = shufflevector <2 x i16> undef, <2 x i16> undef, <3 x i32> - %shuf020 = shufflevector <2 x i16> undef, <2 x i16> undef, <3 x i32> - %shuf022 = shufflevector <2 x i16> undef, <2 x i16> undef, <3 x i32> - %shuf200 = shufflevector <2 x i16> undef, <2 x i16> undef, <3 x i32> - %shuf202 = shufflevector <2 x i16> undef, <2 x i16> undef, <3 x i32> - %shuf220 = shufflevector <2 x i16> undef, <2 x i16> undef, <3 x i32> - %shuf222 = shufflevector <2 x i16> undef, <2 x i16> undef, <3 x i32> - %shuf112 = shufflevector <2 x i16> undef, <2 x i16> undef, <3 x i32> - %shuf121 = shufflevector <2 x i16> undef, <2 x i16> undef, <3 x i32> - %shuf122 = shufflevector <2 x i16> undef, <2 x i16> undef, <3 x i32> - %shuf211 = shufflevector <2 x i16> undef, <2 x i16> undef, <3 x i32> - %shuf212 = shufflevector <2 x i16> undef, <2 x i16> undef, <3 x i32> - %shuf221 = shufflevector <2 x i16> undef, <2 x i16> undef, <3 x i32> + %shuf00 = shufflevector <2 x i16> %vec1, <2 x i16> %vec1, <2 x i32> zeroinitializer + %shuf01 = shufflevector <2 x i16> %vec1, <2 x i16> %vec1, <2 x i32> + %shuf10 = shufflevector <2 x i16> %vec1, <2 x i16> %vec1, <2 x i32> + %shuf11 = shufflevector <2 x i16> %vec1, <2 x i16> %vec1, <2 x i32> + %shuf02 = shufflevector <2 x i16> %vec1, <2 x i16> %vec1, <2 x i32> + %shuf20 = shufflevector <2 x i16> %vec1, <2 x i16> %vec1, <2 x i32> + %shuf22 = shufflevector <2 x i16> %vec1, <2 x i16> %vec1, <2 x i32> + %shuf03 = shufflevector <2 x i16> %vec1, <2 x i16> %vec1, <2 x i32> + %shuf30 = shufflevector <2 x i16> %vec1, <2 x i16> %vec1, <2 x i32> + %shuf33 = shufflevector <2 x i16> %vec1, <2 x i16> %vec1, <2 x i32> + %shuf12 = shufflevector <2 x i16> %vec1, <2 x i16> %vec1, <2 x i32> + %shuf21 = shufflevector <2 x i16> %vec1, <2 x i16> %vec1, <2 x i32> + %shuf13 = shufflevector <2 x i16> %vec1, <2 x i16> %vec1, <2 x i32> + %shuf31 = shufflevector <2 x i16> %vec1, <2 x i16> %vec1, <2 x i32> + %shuf23 = shufflevector <2 x i16> %vec1, <2 x i16> %vec1, <2 x i32> + %shuf32 = shufflevector <2 x i16> %vec1, <2 x i16> %vec1, <2 x i32> + %shuf000 = shufflevector <2 x i16> %vec1, <2 x i16> %vec1, <3 x i32> + %shuf001 = shufflevector <2 x i16> %vec1, <2 x i16> %vec1, <3 x i32> + %shuf010 = shufflevector <2 x i16> %vec1, <2 x i16> %vec1, <3 x i32> + %shuf011 = shufflevector <2 x i16> %vec1, <2 x i16> %vec1, <3 x i32> + %shuf100 = shufflevector <2 x i16> %vec1, <2 x i16> %vec1, <3 x i32> + %shuf101 = shufflevector <2 x i16> %vec1, <2 x i16> %vec1, <3 x i32> + %shuf110 = shufflevector <2 x i16> %vec1, <2 x i16> %vec1, <3 x i32> + %shuf111 = shufflevector <2 x i16> %vec1, <2 x i16> %vec1, <3 x i32> + %shuf002 = shufflevector <2 x i16> %vec1, <2 x i16> %vec1, <3 x i32> + %shuf020 = shufflevector <2 x i16> %vec1, <2 x i16> %vec1, <3 x i32> + %shuf022 = shufflevector <2 x i16> %vec1, <2 x i16> %vec1, <3 x i32> + %shuf200 = shufflevector <2 x i16> %vec1, <2 x i16> %vec1, <3 x i32> + %shuf202 = shufflevector <2 x i16> %vec1, <2 x i16> %vec1, <3 x i32> + %shuf220 = shufflevector <2 x i16> %vec1, <2 x i16> %vec1, <3 x i32> + %shuf222 = shufflevector <2 x i16> %vec1, <2 x i16> %vec1, <3 x i32> + %shuf112 = shufflevector <2 x i16> %vec1, <2 x i16> %vec1, <3 x i32> + %shuf121 = shufflevector <2 x i16> %vec1, <2 x i16> %vec1, <3 x i32> + %shuf122 = shufflevector <2 x i16> %vec1, <2 x i16> %vec1, <3 x i32> + %shuf211 = shufflevector <2 x i16> %vec1, <2 x i16> %vec1, <3 x i32> + %shuf212 = shufflevector <2 x i16> %vec1, <2 x i16> %vec1, <3 x i32> + %shuf221 = shufflevector <2 x i16> %vec1, <2 x i16> %vec1, <3 x i32> + %shuf00_2 = shufflevector <2 x i16> %vec1, <2 x i16> %vec2, <2 x i32> zeroinitializer + %shuf01_2 = shufflevector <2 x i16> %vec1, <2 x i16> %vec2, <2 x i32> + %shuf10_2 = shufflevector <2 x i16> %vec1, <2 x i16> %vec2, <2 x i32> + %shuf11_2 = shufflevector <2 x i16> %vec1, <2 x i16> %vec2, <2 x i32> + %shuf02_2 = shufflevector <2 x i16> %vec1, <2 x i16> %vec2, <2 x i32> + %shuf20_2 = shufflevector <2 x i16> %vec1, <2 x i16> %vec2, <2 x i32> + %shuf22_2 = shufflevector <2 x i16> %vec1, <2 x i16> %vec2, <2 x i32> + %shuf03_2 = shufflevector <2 x i16> %vec1, <2 x i16> %vec2, <2 x i32> + %shuf30_2 = shufflevector <2 x i16> %vec1, <2 x i16> %vec2, <2 x i32> + %shuf33_2 = shufflevector <2 x i16> %vec1, <2 x i16> %vec2, <2 x i32> + %shuf12_2 = shufflevector <2 x i16> %vec1, <2 x i16> %vec2, <2 x i32> + %shuf21_2 = shufflevector <2 x i16> %vec1, <2 x i16> %vec2, <2 x i32> + %shuf13_2 = shufflevector <2 x i16> %vec1, <2 x i16> %vec2, <2 x i32> + %shuf31_2 = shufflevector <2 x i16> %vec1, <2 x i16> %vec2, <2 x i32> + %shuf23_2 = shufflevector <2 x i16> %vec1, <2 x i16> %vec2, <2 x i32> + %shuf32_2 = shufflevector <2 x i16> %vec1, <2 x i16> %vec2, <2 x i32> + %shuf000_2 = shufflevector <2 x i16> %vec1, <2 x i16> %vec2, <3 x i32> + %shuf001_2 = shufflevector <2 x i16> %vec1, <2 x i16> %vec2, <3 x i32> + %shuf010_2 = shufflevector <2 x i16> %vec1, <2 x i16> %vec2, <3 x i32> + %shuf011_2 = shufflevector <2 x i16> %vec1, <2 x i16> %vec2, <3 x i32> + %shuf100_2 = shufflevector <2 x i16> %vec1, <2 x i16> %vec2, <3 x i32> + %shuf101_2 = shufflevector <2 x i16> %vec1, <2 x i16> %vec2, <3 x i32> + %shuf110_2 = shufflevector <2 x i16> %vec1, <2 x i16> %vec2, <3 x i32> + %shuf111_2 = shufflevector <2 x i16> %vec1, <2 x i16> %vec2, <3 x i32> + %shuf002_2 = shufflevector <2 x i16> %vec1, <2 x i16> %vec2, <3 x i32> + %shuf020_2 = shufflevector <2 x i16> %vec1, <2 x i16> %vec2, <3 x i32> + %shuf022_2 = shufflevector <2 x i16> %vec1, <2 x i16> %vec2, <3 x i32> + %shuf200_2 = shufflevector <2 x i16> %vec1, <2 x i16> %vec2, <3 x i32> + %shuf202_2 = shufflevector <2 x i16> %vec1, <2 x i16> %vec2, <3 x i32> + %shuf220_2 = shufflevector <2 x i16> %vec1, <2 x i16> %vec2, <3 x i32> + %shuf222_2 = shufflevector <2 x i16> %vec1, <2 x i16> %vec2, <3 x i32> + %shuf112_2 = shufflevector <2 x i16> %vec1, <2 x i16> %vec2, <3 x i32> + %shuf121_2 = shufflevector <2 x i16> %vec1, <2 x i16> %vec2, <3 x i32> + %shuf122_2 = shufflevector <2 x i16> %vec1, <2 x i16> %vec2, <3 x i32> + %shuf211_2 = shufflevector <2 x i16> %vec1, <2 x i16> %vec2, <3 x i32> + %shuf212_2 = shufflevector <2 x i16> %vec1, <2 x i16> %vec2, <3 x i32> + %shuf221_2 = shufflevector <2 x i16> %vec1, <2 x i16> %vec2, <3 x i32> ret void } ; Should not assert -define amdgpu_kernel void @shufflevector_i8() { +define amdgpu_kernel void @shufflevector_i8(<2 x i8> %vec1, <2 x i8> %vec2) { ; ALL-LABEL: 'shufflevector_i8' -; ALL-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %shuf00 = shufflevector <2 x i8> undef, <2 x i8> undef, <2 x i32> zeroinitializer -; ALL-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf01 = shufflevector <2 x i8> undef, <2 x i8> undef, <2 x i32> -; ALL-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf10 = shufflevector <2 x i8> undef, <2 x i8> undef, <2 x i32> -; ALL-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf11 = shufflevector <2 x i8> undef, <2 x i8> undef, <2 x i32> -; ALL-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf02 = shufflevector <2 x i8> undef, <2 x i8> undef, <2 x i32> -; ALL-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %shuf20 = shufflevector <2 x i8> undef, <2 x i8> undef, <2 x i32> -; ALL-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %shuf22 = shufflevector <2 x i8> undef, <2 x i8> undef, <2 x i32> -; ALL-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf03 = shufflevector <2 x i8> undef, <2 x i8> undef, <2 x i32> -; ALL-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf30 = shufflevector <2 x i8> undef, <2 x i8> undef, <2 x i32> -; ALL-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf33 = shufflevector <2 x i8> undef, <2 x i8> undef, <2 x i32> -; ALL-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf12 = shufflevector <2 x i8> undef, <2 x i8> undef, <2 x i32> -; ALL-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf21 = shufflevector <2 x i8> undef, <2 x i8> undef, <2 x i32> -; ALL-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf13 = shufflevector <2 x i8> undef, <2 x i8> undef, <2 x i32> -; ALL-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf31 = shufflevector <2 x i8> undef, <2 x i8> undef, <2 x i32> -; ALL-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf23 = shufflevector <2 x i8> undef, <2 x i8> undef, <2 x i32> -; ALL-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf32 = shufflevector <2 x i8> undef, <2 x i8> undef, <2 x i32> -; ALL-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf000 = shufflevector <2 x i8> undef, <2 x i8> undef, <3 x i32> zeroinitializer -; ALL-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %shuf001 = shufflevector <2 x i8> undef, <2 x i8> undef, <3 x i32> -; ALL-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %shuf010 = shufflevector <2 x i8> undef, <2 x i8> undef, <3 x i32> -; ALL-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %shuf011 = shufflevector <2 x i8> undef, <2 x i8> undef, <3 x i32> -; ALL-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %shuf100 = shufflevector <2 x i8> undef, <2 x i8> undef, <3 x i32> -; ALL-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %shuf101 = shufflevector <2 x i8> undef, <2 x i8> undef, <3 x i32> -; ALL-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %shuf110 = shufflevector <2 x i8> undef, <2 x i8> undef, <3 x i32> -; ALL-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %shuf111 = shufflevector <2 x i8> undef, <2 x i8> undef, <3 x i32> -; ALL-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %shuf002 = shufflevector <2 x i8> undef, <2 x i8> undef, <3 x i32> -; ALL-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %shuf020 = shufflevector <2 x i8> undef, <2 x i8> undef, <3 x i32> -; ALL-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %shuf022 = shufflevector <2 x i8> undef, <2 x i8> undef, <3 x i32> -; ALL-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %shuf200 = shufflevector <2 x i8> undef, <2 x i8> undef, <3 x i32> -; ALL-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %shuf202 = shufflevector <2 x i8> undef, <2 x i8> undef, <3 x i32> -; ALL-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %shuf220 = shufflevector <2 x i8> undef, <2 x i8> undef, <3 x i32> -; ALL-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf222 = shufflevector <2 x i8> undef, <2 x i8> undef, <3 x i32> -; ALL-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %shuf112 = shufflevector <2 x i8> undef, <2 x i8> undef, <3 x i32> -; ALL-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %shuf121 = shufflevector <2 x i8> undef, <2 x i8> undef, <3 x i32> -; ALL-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %shuf122 = shufflevector <2 x i8> undef, <2 x i8> undef, <3 x i32> -; ALL-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %shuf211 = shufflevector <2 x i8> undef, <2 x i8> undef, <3 x i32> -; ALL-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %shuf212 = shufflevector <2 x i8> undef, <2 x i8> undef, <3 x i32> -; ALL-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %shuf221 = shufflevector <2 x i8> undef, <2 x i8> undef, <3 x i32> +; ALL-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %shuf00 = shufflevector <2 x i8> %vec1, <2 x i8> %vec1, <2 x i32> zeroinitializer +; ALL-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf01 = shufflevector <2 x i8> %vec1, <2 x i8> %vec1, <2 x i32> +; ALL-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf10 = shufflevector <2 x i8> %vec1, <2 x i8> %vec1, <2 x i32> +; ALL-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf11 = shufflevector <2 x i8> %vec1, <2 x i8> %vec1, <2 x i32> +; ALL-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf02 = shufflevector <2 x i8> %vec1, <2 x i8> %vec1, <2 x i32> +; ALL-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %shuf20 = shufflevector <2 x i8> %vec1, <2 x i8> %vec1, <2 x i32> +; ALL-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %shuf22 = shufflevector <2 x i8> %vec1, <2 x i8> %vec1, <2 x i32> +; ALL-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf03 = shufflevector <2 x i8> %vec1, <2 x i8> %vec1, <2 x i32> +; ALL-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf30 = shufflevector <2 x i8> %vec1, <2 x i8> %vec1, <2 x i32> +; ALL-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf33 = shufflevector <2 x i8> %vec1, <2 x i8> %vec1, <2 x i32> +; ALL-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf12 = shufflevector <2 x i8> %vec1, <2 x i8> %vec1, <2 x i32> +; ALL-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf21 = shufflevector <2 x i8> %vec1, <2 x i8> %vec1, <2 x i32> +; ALL-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf13 = shufflevector <2 x i8> %vec1, <2 x i8> %vec1, <2 x i32> +; ALL-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf31 = shufflevector <2 x i8> %vec1, <2 x i8> %vec1, <2 x i32> +; ALL-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf23 = shufflevector <2 x i8> %vec1, <2 x i8> %vec1, <2 x i32> +; ALL-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf32 = shufflevector <2 x i8> %vec1, <2 x i8> %vec1, <2 x i32> +; ALL-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %shuf000 = shufflevector <2 x i8> %vec1, <2 x i8> %vec1, <3 x i32> zeroinitializer +; ALL-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %shuf001 = shufflevector <2 x i8> %vec1, <2 x i8> %vec1, <3 x i32> +; ALL-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %shuf010 = shufflevector <2 x i8> %vec1, <2 x i8> %vec1, <3 x i32> +; ALL-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %shuf011 = shufflevector <2 x i8> %vec1, <2 x i8> %vec1, <3 x i32> +; ALL-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %shuf100 = shufflevector <2 x i8> %vec1, <2 x i8> %vec1, <3 x i32> +; ALL-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %shuf101 = shufflevector <2 x i8> %vec1, <2 x i8> %vec1, <3 x i32> +; ALL-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %shuf110 = shufflevector <2 x i8> %vec1, <2 x i8> %vec1, <3 x i32> +; ALL-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %shuf111 = shufflevector <2 x i8> %vec1, <2 x i8> %vec1, <3 x i32> +; ALL-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %shuf002 = shufflevector <2 x i8> %vec1, <2 x i8> %vec1, <3 x i32> +; ALL-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %shuf020 = shufflevector <2 x i8> %vec1, <2 x i8> %vec1, <3 x i32> +; ALL-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %shuf022 = shufflevector <2 x i8> %vec1, <2 x i8> %vec1, <3 x i32> +; ALL-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %shuf200 = shufflevector <2 x i8> %vec1, <2 x i8> %vec1, <3 x i32> +; ALL-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %shuf202 = shufflevector <2 x i8> %vec1, <2 x i8> %vec1, <3 x i32> +; ALL-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %shuf220 = shufflevector <2 x i8> %vec1, <2 x i8> %vec1, <3 x i32> +; ALL-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %shuf222 = shufflevector <2 x i8> %vec1, <2 x i8> %vec1, <3 x i32> +; ALL-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %shuf112 = shufflevector <2 x i8> %vec1, <2 x i8> %vec1, <3 x i32> +; ALL-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %shuf121 = shufflevector <2 x i8> %vec1, <2 x i8> %vec1, <3 x i32> +; ALL-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %shuf122 = shufflevector <2 x i8> %vec1, <2 x i8> %vec1, <3 x i32> +; ALL-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %shuf211 = shufflevector <2 x i8> %vec1, <2 x i8> %vec1, <3 x i32> +; ALL-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %shuf212 = shufflevector <2 x i8> %vec1, <2 x i8> %vec1, <3 x i32> +; ALL-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %shuf221 = shufflevector <2 x i8> %vec1, <2 x i8> %vec1, <3 x i32> +; ALL-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %shuf00_2 = shufflevector <2 x i8> %vec1, <2 x i8> %vec2, <2 x i32> zeroinitializer +; ALL-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf01_2 = shufflevector <2 x i8> %vec1, <2 x i8> %vec2, <2 x i32> +; ALL-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf10_2 = shufflevector <2 x i8> %vec1, <2 x i8> %vec2, <2 x i32> +; ALL-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf11_2 = shufflevector <2 x i8> %vec1, <2 x i8> %vec2, <2 x i32> +; ALL-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf02_2 = shufflevector <2 x i8> %vec1, <2 x i8> %vec2, <2 x i32> +; ALL-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %shuf20_2 = shufflevector <2 x i8> %vec1, <2 x i8> %vec2, <2 x i32> +; ALL-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %shuf22_2 = shufflevector <2 x i8> %vec1, <2 x i8> %vec2, <2 x i32> +; ALL-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf03_2 = shufflevector <2 x i8> %vec1, <2 x i8> %vec2, <2 x i32> +; ALL-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf30_2 = shufflevector <2 x i8> %vec1, <2 x i8> %vec2, <2 x i32> +; ALL-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf33_2 = shufflevector <2 x i8> %vec1, <2 x i8> %vec2, <2 x i32> +; ALL-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf12_2 = shufflevector <2 x i8> %vec1, <2 x i8> %vec2, <2 x i32> +; ALL-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf21_2 = shufflevector <2 x i8> %vec1, <2 x i8> %vec2, <2 x i32> +; ALL-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf13_2 = shufflevector <2 x i8> %vec1, <2 x i8> %vec2, <2 x i32> +; ALL-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf31_2 = shufflevector <2 x i8> %vec1, <2 x i8> %vec2, <2 x i32> +; ALL-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf23_2 = shufflevector <2 x i8> %vec1, <2 x i8> %vec2, <2 x i32> +; ALL-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf32_2 = shufflevector <2 x i8> %vec1, <2 x i8> %vec2, <2 x i32> +; ALL-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %shuf000_2 = shufflevector <2 x i8> %vec1, <2 x i8> %vec2, <3 x i32> zeroinitializer +; ALL-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %shuf001_2 = shufflevector <2 x i8> %vec1, <2 x i8> %vec2, <3 x i32> +; ALL-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %shuf010_2 = shufflevector <2 x i8> %vec1, <2 x i8> %vec2, <3 x i32> +; ALL-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %shuf011_2 = shufflevector <2 x i8> %vec1, <2 x i8> %vec2, <3 x i32> +; ALL-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %shuf100_2 = shufflevector <2 x i8> %vec1, <2 x i8> %vec2, <3 x i32> +; ALL-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %shuf101_2 = shufflevector <2 x i8> %vec1, <2 x i8> %vec2, <3 x i32> +; ALL-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %shuf110_2 = shufflevector <2 x i8> %vec1, <2 x i8> %vec2, <3 x i32> +; ALL-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %shuf111_2 = shufflevector <2 x i8> %vec1, <2 x i8> %vec2, <3 x i32> +; ALL-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %shuf002_2 = shufflevector <2 x i8> %vec1, <2 x i8> %vec2, <3 x i32> +; ALL-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %shuf020_2 = shufflevector <2 x i8> %vec1, <2 x i8> %vec2, <3 x i32> +; ALL-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %shuf022_2 = shufflevector <2 x i8> %vec1, <2 x i8> %vec2, <3 x i32> +; ALL-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %shuf200_2 = shufflevector <2 x i8> %vec1, <2 x i8> %vec2, <3 x i32> +; ALL-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %shuf202_2 = shufflevector <2 x i8> %vec1, <2 x i8> %vec2, <3 x i32> +; ALL-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %shuf220_2 = shufflevector <2 x i8> %vec1, <2 x i8> %vec2, <3 x i32> +; ALL-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %shuf222_2 = shufflevector <2 x i8> %vec1, <2 x i8> %vec2, <3 x i32> +; ALL-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %shuf112_2 = shufflevector <2 x i8> %vec1, <2 x i8> %vec2, <3 x i32> +; ALL-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %shuf121_2 = shufflevector <2 x i8> %vec1, <2 x i8> %vec2, <3 x i32> +; ALL-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %shuf122_2 = shufflevector <2 x i8> %vec1, <2 x i8> %vec2, <3 x i32> +; ALL-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %shuf211_2 = shufflevector <2 x i8> %vec1, <2 x i8> %vec2, <3 x i32> +; ALL-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %shuf212_2 = shufflevector <2 x i8> %vec1, <2 x i8> %vec2, <3 x i32> +; ALL-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %shuf221_2 = shufflevector <2 x i8> %vec1, <2 x i8> %vec2, <3 x i32> ; ALL-NEXT: Cost Model: Found an estimated cost of 10 for instruction: ret void ; ; ALL-SIZE-LABEL: 'shufflevector_i8' -; ALL-SIZE-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %shuf00 = shufflevector <2 x i8> undef, <2 x i8> undef, <2 x i32> zeroinitializer -; ALL-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf01 = shufflevector <2 x i8> undef, <2 x i8> undef, <2 x i32> -; ALL-SIZE-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf10 = shufflevector <2 x i8> undef, <2 x i8> undef, <2 x i32> -; ALL-SIZE-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf11 = shufflevector <2 x i8> undef, <2 x i8> undef, <2 x i32> -; ALL-SIZE-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf02 = shufflevector <2 x i8> undef, <2 x i8> undef, <2 x i32> -; ALL-SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %shuf20 = shufflevector <2 x i8> undef, <2 x i8> undef, <2 x i32> -; ALL-SIZE-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %shuf22 = shufflevector <2 x i8> undef, <2 x i8> undef, <2 x i32> -; ALL-SIZE-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf03 = shufflevector <2 x i8> undef, <2 x i8> undef, <2 x i32> -; ALL-SIZE-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf30 = shufflevector <2 x i8> undef, <2 x i8> undef, <2 x i32> -; ALL-SIZE-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf33 = shufflevector <2 x i8> undef, <2 x i8> undef, <2 x i32> -; ALL-SIZE-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf12 = shufflevector <2 x i8> undef, <2 x i8> undef, <2 x i32> -; ALL-SIZE-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf21 = shufflevector <2 x i8> undef, <2 x i8> undef, <2 x i32> -; ALL-SIZE-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf13 = shufflevector <2 x i8> undef, <2 x i8> undef, <2 x i32> -; ALL-SIZE-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf31 = shufflevector <2 x i8> undef, <2 x i8> undef, <2 x i32> -; ALL-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf23 = shufflevector <2 x i8> undef, <2 x i8> undef, <2 x i32> -; ALL-SIZE-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf32 = shufflevector <2 x i8> undef, <2 x i8> undef, <2 x i32> -; ALL-SIZE-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf000 = shufflevector <2 x i8> undef, <2 x i8> undef, <3 x i32> zeroinitializer -; ALL-SIZE-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %shuf001 = shufflevector <2 x i8> undef, <2 x i8> undef, <3 x i32> -; ALL-SIZE-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %shuf010 = shufflevector <2 x i8> undef, <2 x i8> undef, <3 x i32> -; ALL-SIZE-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %shuf011 = shufflevector <2 x i8> undef, <2 x i8> undef, <3 x i32> -; ALL-SIZE-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %shuf100 = shufflevector <2 x i8> undef, <2 x i8> undef, <3 x i32> -; ALL-SIZE-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %shuf101 = shufflevector <2 x i8> undef, <2 x i8> undef, <3 x i32> -; ALL-SIZE-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %shuf110 = shufflevector <2 x i8> undef, <2 x i8> undef, <3 x i32> -; ALL-SIZE-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %shuf111 = shufflevector <2 x i8> undef, <2 x i8> undef, <3 x i32> -; ALL-SIZE-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %shuf002 = shufflevector <2 x i8> undef, <2 x i8> undef, <3 x i32> -; ALL-SIZE-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %shuf020 = shufflevector <2 x i8> undef, <2 x i8> undef, <3 x i32> -; ALL-SIZE-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %shuf022 = shufflevector <2 x i8> undef, <2 x i8> undef, <3 x i32> -; ALL-SIZE-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %shuf200 = shufflevector <2 x i8> undef, <2 x i8> undef, <3 x i32> -; ALL-SIZE-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %shuf202 = shufflevector <2 x i8> undef, <2 x i8> undef, <3 x i32> -; ALL-SIZE-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %shuf220 = shufflevector <2 x i8> undef, <2 x i8> undef, <3 x i32> -; ALL-SIZE-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf222 = shufflevector <2 x i8> undef, <2 x i8> undef, <3 x i32> -; ALL-SIZE-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %shuf112 = shufflevector <2 x i8> undef, <2 x i8> undef, <3 x i32> -; ALL-SIZE-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %shuf121 = shufflevector <2 x i8> undef, <2 x i8> undef, <3 x i32> -; ALL-SIZE-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %shuf122 = shufflevector <2 x i8> undef, <2 x i8> undef, <3 x i32> -; ALL-SIZE-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %shuf211 = shufflevector <2 x i8> undef, <2 x i8> undef, <3 x i32> -; ALL-SIZE-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %shuf212 = shufflevector <2 x i8> undef, <2 x i8> undef, <3 x i32> -; ALL-SIZE-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %shuf221 = shufflevector <2 x i8> undef, <2 x i8> undef, <3 x i32> +; ALL-SIZE-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %shuf00 = shufflevector <2 x i8> %vec1, <2 x i8> %vec1, <2 x i32> zeroinitializer +; ALL-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf01 = shufflevector <2 x i8> %vec1, <2 x i8> %vec1, <2 x i32> +; ALL-SIZE-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf10 = shufflevector <2 x i8> %vec1, <2 x i8> %vec1, <2 x i32> +; ALL-SIZE-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf11 = shufflevector <2 x i8> %vec1, <2 x i8> %vec1, <2 x i32> +; ALL-SIZE-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf02 = shufflevector <2 x i8> %vec1, <2 x i8> %vec1, <2 x i32> +; ALL-SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %shuf20 = shufflevector <2 x i8> %vec1, <2 x i8> %vec1, <2 x i32> +; ALL-SIZE-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %shuf22 = shufflevector <2 x i8> %vec1, <2 x i8> %vec1, <2 x i32> +; ALL-SIZE-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf03 = shufflevector <2 x i8> %vec1, <2 x i8> %vec1, <2 x i32> +; ALL-SIZE-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf30 = shufflevector <2 x i8> %vec1, <2 x i8> %vec1, <2 x i32> +; ALL-SIZE-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf33 = shufflevector <2 x i8> %vec1, <2 x i8> %vec1, <2 x i32> +; ALL-SIZE-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf12 = shufflevector <2 x i8> %vec1, <2 x i8> %vec1, <2 x i32> +; ALL-SIZE-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf21 = shufflevector <2 x i8> %vec1, <2 x i8> %vec1, <2 x i32> +; ALL-SIZE-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf13 = shufflevector <2 x i8> %vec1, <2 x i8> %vec1, <2 x i32> +; ALL-SIZE-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf31 = shufflevector <2 x i8> %vec1, <2 x i8> %vec1, <2 x i32> +; ALL-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf23 = shufflevector <2 x i8> %vec1, <2 x i8> %vec1, <2 x i32> +; ALL-SIZE-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf32 = shufflevector <2 x i8> %vec1, <2 x i8> %vec1, <2 x i32> +; ALL-SIZE-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %shuf000 = shufflevector <2 x i8> %vec1, <2 x i8> %vec1, <3 x i32> zeroinitializer +; ALL-SIZE-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %shuf001 = shufflevector <2 x i8> %vec1, <2 x i8> %vec1, <3 x i32> +; ALL-SIZE-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %shuf010 = shufflevector <2 x i8> %vec1, <2 x i8> %vec1, <3 x i32> +; ALL-SIZE-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %shuf011 = shufflevector <2 x i8> %vec1, <2 x i8> %vec1, <3 x i32> +; ALL-SIZE-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %shuf100 = shufflevector <2 x i8> %vec1, <2 x i8> %vec1, <3 x i32> +; ALL-SIZE-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %shuf101 = shufflevector <2 x i8> %vec1, <2 x i8> %vec1, <3 x i32> +; ALL-SIZE-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %shuf110 = shufflevector <2 x i8> %vec1, <2 x i8> %vec1, <3 x i32> +; ALL-SIZE-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %shuf111 = shufflevector <2 x i8> %vec1, <2 x i8> %vec1, <3 x i32> +; ALL-SIZE-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %shuf002 = shufflevector <2 x i8> %vec1, <2 x i8> %vec1, <3 x i32> +; ALL-SIZE-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %shuf020 = shufflevector <2 x i8> %vec1, <2 x i8> %vec1, <3 x i32> +; ALL-SIZE-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %shuf022 = shufflevector <2 x i8> %vec1, <2 x i8> %vec1, <3 x i32> +; ALL-SIZE-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %shuf200 = shufflevector <2 x i8> %vec1, <2 x i8> %vec1, <3 x i32> +; ALL-SIZE-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %shuf202 = shufflevector <2 x i8> %vec1, <2 x i8> %vec1, <3 x i32> +; ALL-SIZE-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %shuf220 = shufflevector <2 x i8> %vec1, <2 x i8> %vec1, <3 x i32> +; ALL-SIZE-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %shuf222 = shufflevector <2 x i8> %vec1, <2 x i8> %vec1, <3 x i32> +; ALL-SIZE-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %shuf112 = shufflevector <2 x i8> %vec1, <2 x i8> %vec1, <3 x i32> +; ALL-SIZE-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %shuf121 = shufflevector <2 x i8> %vec1, <2 x i8> %vec1, <3 x i32> +; ALL-SIZE-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %shuf122 = shufflevector <2 x i8> %vec1, <2 x i8> %vec1, <3 x i32> +; ALL-SIZE-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %shuf211 = shufflevector <2 x i8> %vec1, <2 x i8> %vec1, <3 x i32> +; ALL-SIZE-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %shuf212 = shufflevector <2 x i8> %vec1, <2 x i8> %vec1, <3 x i32> +; ALL-SIZE-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %shuf221 = shufflevector <2 x i8> %vec1, <2 x i8> %vec1, <3 x i32> +; ALL-SIZE-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %shuf00_2 = shufflevector <2 x i8> %vec1, <2 x i8> %vec2, <2 x i32> zeroinitializer +; ALL-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf01_2 = shufflevector <2 x i8> %vec1, <2 x i8> %vec2, <2 x i32> +; ALL-SIZE-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf10_2 = shufflevector <2 x i8> %vec1, <2 x i8> %vec2, <2 x i32> +; ALL-SIZE-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf11_2 = shufflevector <2 x i8> %vec1, <2 x i8> %vec2, <2 x i32> +; ALL-SIZE-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf02_2 = shufflevector <2 x i8> %vec1, <2 x i8> %vec2, <2 x i32> +; ALL-SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %shuf20_2 = shufflevector <2 x i8> %vec1, <2 x i8> %vec2, <2 x i32> +; ALL-SIZE-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %shuf22_2 = shufflevector <2 x i8> %vec1, <2 x i8> %vec2, <2 x i32> +; ALL-SIZE-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf03_2 = shufflevector <2 x i8> %vec1, <2 x i8> %vec2, <2 x i32> +; ALL-SIZE-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf30_2 = shufflevector <2 x i8> %vec1, <2 x i8> %vec2, <2 x i32> +; ALL-SIZE-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf33_2 = shufflevector <2 x i8> %vec1, <2 x i8> %vec2, <2 x i32> +; ALL-SIZE-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf12_2 = shufflevector <2 x i8> %vec1, <2 x i8> %vec2, <2 x i32> +; ALL-SIZE-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf21_2 = shufflevector <2 x i8> %vec1, <2 x i8> %vec2, <2 x i32> +; ALL-SIZE-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf13_2 = shufflevector <2 x i8> %vec1, <2 x i8> %vec2, <2 x i32> +; ALL-SIZE-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf31_2 = shufflevector <2 x i8> %vec1, <2 x i8> %vec2, <2 x i32> +; ALL-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf23_2 = shufflevector <2 x i8> %vec1, <2 x i8> %vec2, <2 x i32> +; ALL-SIZE-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %shuf32_2 = shufflevector <2 x i8> %vec1, <2 x i8> %vec2, <2 x i32> +; ALL-SIZE-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %shuf000_2 = shufflevector <2 x i8> %vec1, <2 x i8> %vec2, <3 x i32> zeroinitializer +; ALL-SIZE-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %shuf001_2 = shufflevector <2 x i8> %vec1, <2 x i8> %vec2, <3 x i32> +; ALL-SIZE-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %shuf010_2 = shufflevector <2 x i8> %vec1, <2 x i8> %vec2, <3 x i32> +; ALL-SIZE-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %shuf011_2 = shufflevector <2 x i8> %vec1, <2 x i8> %vec2, <3 x i32> +; ALL-SIZE-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %shuf100_2 = shufflevector <2 x i8> %vec1, <2 x i8> %vec2, <3 x i32> +; ALL-SIZE-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %shuf101_2 = shufflevector <2 x i8> %vec1, <2 x i8> %vec2, <3 x i32> +; ALL-SIZE-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %shuf110_2 = shufflevector <2 x i8> %vec1, <2 x i8> %vec2, <3 x i32> +; ALL-SIZE-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %shuf111_2 = shufflevector <2 x i8> %vec1, <2 x i8> %vec2, <3 x i32> +; ALL-SIZE-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %shuf002_2 = shufflevector <2 x i8> %vec1, <2 x i8> %vec2, <3 x i32> +; ALL-SIZE-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %shuf020_2 = shufflevector <2 x i8> %vec1, <2 x i8> %vec2, <3 x i32> +; ALL-SIZE-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %shuf022_2 = shufflevector <2 x i8> %vec1, <2 x i8> %vec2, <3 x i32> +; ALL-SIZE-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %shuf200_2 = shufflevector <2 x i8> %vec1, <2 x i8> %vec2, <3 x i32> +; ALL-SIZE-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %shuf202_2 = shufflevector <2 x i8> %vec1, <2 x i8> %vec2, <3 x i32> +; ALL-SIZE-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %shuf220_2 = shufflevector <2 x i8> %vec1, <2 x i8> %vec2, <3 x i32> +; ALL-SIZE-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %shuf222_2 = shufflevector <2 x i8> %vec1, <2 x i8> %vec2, <3 x i32> +; ALL-SIZE-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %shuf112_2 = shufflevector <2 x i8> %vec1, <2 x i8> %vec2, <3 x i32> +; ALL-SIZE-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %shuf121_2 = shufflevector <2 x i8> %vec1, <2 x i8> %vec2, <3 x i32> +; ALL-SIZE-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %shuf122_2 = shufflevector <2 x i8> %vec1, <2 x i8> %vec2, <3 x i32> +; ALL-SIZE-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %shuf211_2 = shufflevector <2 x i8> %vec1, <2 x i8> %vec2, <3 x i32> +; ALL-SIZE-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %shuf212_2 = shufflevector <2 x i8> %vec1, <2 x i8> %vec2, <3 x i32> +; ALL-SIZE-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %shuf221_2 = shufflevector <2 x i8> %vec1, <2 x i8> %vec2, <3 x i32> ; ALL-SIZE-NEXT: Cost Model: Found an estimated cost of 1 for instruction: ret void ; - %shuf00 = shufflevector <2 x i8> undef, <2 x i8> undef, <2 x i32> zeroinitializer - %shuf01 = shufflevector <2 x i8> undef, <2 x i8> undef, <2 x i32> - %shuf10 = shufflevector <2 x i8> undef, <2 x i8> undef, <2 x i32> - %shuf11 = shufflevector <2 x i8> undef, <2 x i8> undef, <2 x i32> - %shuf02 = shufflevector <2 x i8> undef, <2 x i8> undef, <2 x i32> - %shuf20 = shufflevector <2 x i8> undef, <2 x i8> undef, <2 x i32> - %shuf22 = shufflevector <2 x i8> undef, <2 x i8> undef, <2 x i32> - %shuf03 = shufflevector <2 x i8> undef, <2 x i8> undef, <2 x i32> - %shuf30 = shufflevector <2 x i8> undef, <2 x i8> undef, <2 x i32> - %shuf33 = shufflevector <2 x i8> undef, <2 x i8> undef, <2 x i32> - %shuf12 = shufflevector <2 x i8> undef, <2 x i8> undef, <2 x i32> - %shuf21 = shufflevector <2 x i8> undef, <2 x i8> undef, <2 x i32> - %shuf13 = shufflevector <2 x i8> undef, <2 x i8> undef, <2 x i32> - %shuf31 = shufflevector <2 x i8> undef, <2 x i8> undef, <2 x i32> - %shuf23 = shufflevector <2 x i8> undef, <2 x i8> undef, <2 x i32> - %shuf32 = shufflevector <2 x i8> undef, <2 x i8> undef, <2 x i32> - %shuf000 = shufflevector <2 x i8> undef, <2 x i8> undef, <3 x i32> - %shuf001 = shufflevector <2 x i8> undef, <2 x i8> undef, <3 x i32> - %shuf010 = shufflevector <2 x i8> undef, <2 x i8> undef, <3 x i32> - %shuf011 = shufflevector <2 x i8> undef, <2 x i8> undef, <3 x i32> - %shuf100 = shufflevector <2 x i8> undef, <2 x i8> undef, <3 x i32> - %shuf101 = shufflevector <2 x i8> undef, <2 x i8> undef, <3 x i32> - %shuf110 = shufflevector <2 x i8> undef, <2 x i8> undef, <3 x i32> - %shuf111 = shufflevector <2 x i8> undef, <2 x i8> undef, <3 x i32> - %shuf002 = shufflevector <2 x i8> undef, <2 x i8> undef, <3 x i32> - %shuf020 = shufflevector <2 x i8> undef, <2 x i8> undef, <3 x i32> - %shuf022 = shufflevector <2 x i8> undef, <2 x i8> undef, <3 x i32> - %shuf200 = shufflevector <2 x i8> undef, <2 x i8> undef, <3 x i32> - %shuf202 = shufflevector <2 x i8> undef, <2 x i8> undef, <3 x i32> - %shuf220 = shufflevector <2 x i8> undef, <2 x i8> undef, <3 x i32> - %shuf222 = shufflevector <2 x i8> undef, <2 x i8> undef, <3 x i32> - %shuf112 = shufflevector <2 x i8> undef, <2 x i8> undef, <3 x i32> - %shuf121 = shufflevector <2 x i8> undef, <2 x i8> undef, <3 x i32> - %shuf122 = shufflevector <2 x i8> undef, <2 x i8> undef, <3 x i32> - %shuf211 = shufflevector <2 x i8> undef, <2 x i8> undef, <3 x i32> - %shuf212 = shufflevector <2 x i8> undef, <2 x i8> undef, <3 x i32> - %shuf221 = shufflevector <2 x i8> undef, <2 x i8> undef, <3 x i32> + %shuf00 = shufflevector <2 x i8> %vec1, <2 x i8> %vec1, <2 x i32> zeroinitializer + %shuf01 = shufflevector <2 x i8> %vec1, <2 x i8> %vec1, <2 x i32> + %shuf10 = shufflevector <2 x i8> %vec1, <2 x i8> %vec1, <2 x i32> + %shuf11 = shufflevector <2 x i8> %vec1, <2 x i8> %vec1, <2 x i32> + %shuf02 = shufflevector <2 x i8> %vec1, <2 x i8> %vec1, <2 x i32> + %shuf20 = shufflevector <2 x i8> %vec1, <2 x i8> %vec1, <2 x i32> + %shuf22 = shufflevector <2 x i8> %vec1, <2 x i8> %vec1, <2 x i32> + %shuf03 = shufflevector <2 x i8> %vec1, <2 x i8> %vec1, <2 x i32> + %shuf30 = shufflevector <2 x i8> %vec1, <2 x i8> %vec1, <2 x i32> + %shuf33 = shufflevector <2 x i8> %vec1, <2 x i8> %vec1, <2 x i32> + %shuf12 = shufflevector <2 x i8> %vec1, <2 x i8> %vec1, <2 x i32> + %shuf21 = shufflevector <2 x i8> %vec1, <2 x i8> %vec1, <2 x i32> + %shuf13 = shufflevector <2 x i8> %vec1, <2 x i8> %vec1, <2 x i32> + %shuf31 = shufflevector <2 x i8> %vec1, <2 x i8> %vec1, <2 x i32> + %shuf23 = shufflevector <2 x i8> %vec1, <2 x i8> %vec1, <2 x i32> + %shuf32 = shufflevector <2 x i8> %vec1, <2 x i8> %vec1, <2 x i32> + %shuf000 = shufflevector <2 x i8> %vec1, <2 x i8> %vec1, <3 x i32> + %shuf001 = shufflevector <2 x i8> %vec1, <2 x i8> %vec1, <3 x i32> + %shuf010 = shufflevector <2 x i8> %vec1, <2 x i8> %vec1, <3 x i32> + %shuf011 = shufflevector <2 x i8> %vec1, <2 x i8> %vec1, <3 x i32> + %shuf100 = shufflevector <2 x i8> %vec1, <2 x i8> %vec1, <3 x i32> + %shuf101 = shufflevector <2 x i8> %vec1, <2 x i8> %vec1, <3 x i32> + %shuf110 = shufflevector <2 x i8> %vec1, <2 x i8> %vec1, <3 x i32> + %shuf111 = shufflevector <2 x i8> %vec1, <2 x i8> %vec1, <3 x i32> + %shuf002 = shufflevector <2 x i8> %vec1, <2 x i8> %vec1, <3 x i32> + %shuf020 = shufflevector <2 x i8> %vec1, <2 x i8> %vec1, <3 x i32> + %shuf022 = shufflevector <2 x i8> %vec1, <2 x i8> %vec1, <3 x i32> + %shuf200 = shufflevector <2 x i8> %vec1, <2 x i8> %vec1, <3 x i32> + %shuf202 = shufflevector <2 x i8> %vec1, <2 x i8> %vec1, <3 x i32> + %shuf220 = shufflevector <2 x i8> %vec1, <2 x i8> %vec1, <3 x i32> + %shuf222 = shufflevector <2 x i8> %vec1, <2 x i8> %vec1, <3 x i32> + %shuf112 = shufflevector <2 x i8> %vec1, <2 x i8> %vec1, <3 x i32> + %shuf121 = shufflevector <2 x i8> %vec1, <2 x i8> %vec1, <3 x i32> + %shuf122 = shufflevector <2 x i8> %vec1, <2 x i8> %vec1, <3 x i32> + %shuf211 = shufflevector <2 x i8> %vec1, <2 x i8> %vec1, <3 x i32> + %shuf212 = shufflevector <2 x i8> %vec1, <2 x i8> %vec1, <3 x i32> + %shuf221 = shufflevector <2 x i8> %vec1, <2 x i8> %vec1, <3 x i32> + %shuf00_2 = shufflevector <2 x i8> %vec1, <2 x i8> %vec2, <2 x i32> zeroinitializer + %shuf01_2 = shufflevector <2 x i8> %vec1, <2 x i8> %vec2, <2 x i32> + %shuf10_2 = shufflevector <2 x i8> %vec1, <2 x i8> %vec2, <2 x i32> + %shuf11_2 = shufflevector <2 x i8> %vec1, <2 x i8> %vec2, <2 x i32> + %shuf02_2 = shufflevector <2 x i8> %vec1, <2 x i8> %vec2, <2 x i32> + %shuf20_2 = shufflevector <2 x i8> %vec1, <2 x i8> %vec2, <2 x i32> + %shuf22_2 = shufflevector <2 x i8> %vec1, <2 x i8> %vec2, <2 x i32> + %shuf03_2 = shufflevector <2 x i8> %vec1, <2 x i8> %vec2, <2 x i32> + %shuf30_2 = shufflevector <2 x i8> %vec1, <2 x i8> %vec2, <2 x i32> + %shuf33_2 = shufflevector <2 x i8> %vec1, <2 x i8> %vec2, <2 x i32> + %shuf12_2 = shufflevector <2 x i8> %vec1, <2 x i8> %vec2, <2 x i32> + %shuf21_2 = shufflevector <2 x i8> %vec1, <2 x i8> %vec2, <2 x i32> + %shuf13_2 = shufflevector <2 x i8> %vec1, <2 x i8> %vec2, <2 x i32> + %shuf31_2 = shufflevector <2 x i8> %vec1, <2 x i8> %vec2, <2 x i32> + %shuf23_2 = shufflevector <2 x i8> %vec1, <2 x i8> %vec2, <2 x i32> + %shuf32_2 = shufflevector <2 x i8> %vec1, <2 x i8> %vec2, <2 x i32> + %shuf000_2 = shufflevector <2 x i8> %vec1, <2 x i8> %vec2, <3 x i32> + %shuf001_2 = shufflevector <2 x i8> %vec1, <2 x i8> %vec2, <3 x i32> + %shuf010_2 = shufflevector <2 x i8> %vec1, <2 x i8> %vec2, <3 x i32> + %shuf011_2 = shufflevector <2 x i8> %vec1, <2 x i8> %vec2, <3 x i32> + %shuf100_2 = shufflevector <2 x i8> %vec1, <2 x i8> %vec2, <3 x i32> + %shuf101_2 = shufflevector <2 x i8> %vec1, <2 x i8> %vec2, <3 x i32> + %shuf110_2 = shufflevector <2 x i8> %vec1, <2 x i8> %vec2, <3 x i32> + %shuf111_2 = shufflevector <2 x i8> %vec1, <2 x i8> %vec2, <3 x i32> + %shuf002_2 = shufflevector <2 x i8> %vec1, <2 x i8> %vec2, <3 x i32> + %shuf020_2 = shufflevector <2 x i8> %vec1, <2 x i8> %vec2, <3 x i32> + %shuf022_2 = shufflevector <2 x i8> %vec1, <2 x i8> %vec2, <3 x i32> + %shuf200_2 = shufflevector <2 x i8> %vec1, <2 x i8> %vec2, <3 x i32> + %shuf202_2 = shufflevector <2 x i8> %vec1, <2 x i8> %vec2, <3 x i32> + %shuf220_2 = shufflevector <2 x i8> %vec1, <2 x i8> %vec2, <3 x i32> + %shuf222_2 = shufflevector <2 x i8> %vec1, <2 x i8> %vec2, <3 x i32> + %shuf112_2 = shufflevector <2 x i8> %vec1, <2 x i8> %vec2, <3 x i32> + %shuf121_2 = shufflevector <2 x i8> %vec1, <2 x i8> %vec2, <3 x i32> + %shuf122_2 = shufflevector <2 x i8> %vec1, <2 x i8> %vec2, <3 x i32> + %shuf211_2 = shufflevector <2 x i8> %vec1, <2 x i8> %vec2, <3 x i32> + %shuf212_2 = shufflevector <2 x i8> %vec1, <2 x i8> %vec2, <3 x i32> + %shuf221_2 = shufflevector <2 x i8> %vec1, <2 x i8> %vec2, <3 x i32> ret void } -define amdgpu_kernel void @shufflevector_i32() { +define amdgpu_kernel void @shufflevector_i32(<2 x i32> %vec1, <2 x i32> %vec2) { ; ALL-LABEL: 'shufflevector_i32' -; ALL-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf00 = shufflevector <2 x i32> undef, <2 x i32> undef, <2 x i32> zeroinitializer -; ALL-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf01 = shufflevector <2 x i32> undef, <2 x i32> undef, <2 x i32> -; ALL-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf10 = shufflevector <2 x i32> undef, <2 x i32> undef, <2 x i32> -; ALL-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf11 = shufflevector <2 x i32> undef, <2 x i32> undef, <2 x i32> -; ALL-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf02 = shufflevector <2 x i32> undef, <2 x i32> undef, <2 x i32> -; ALL-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf20 = shufflevector <2 x i32> undef, <2 x i32> undef, <2 x i32> -; ALL-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf22 = shufflevector <2 x i32> undef, <2 x i32> undef, <2 x i32> -; ALL-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf03 = shufflevector <2 x i32> undef, <2 x i32> undef, <2 x i32> -; ALL-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf30 = shufflevector <2 x i32> undef, <2 x i32> undef, <2 x i32> -; ALL-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf33 = shufflevector <2 x i32> undef, <2 x i32> undef, <2 x i32> -; ALL-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf12 = shufflevector <2 x i32> undef, <2 x i32> undef, <2 x i32> -; ALL-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf21 = shufflevector <2 x i32> undef, <2 x i32> undef, <2 x i32> -; ALL-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf13 = shufflevector <2 x i32> undef, <2 x i32> undef, <2 x i32> -; ALL-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf31 = shufflevector <2 x i32> undef, <2 x i32> undef, <2 x i32> -; ALL-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf23 = shufflevector <2 x i32> undef, <2 x i32> undef, <2 x i32> -; ALL-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf32 = shufflevector <2 x i32> undef, <2 x i32> undef, <2 x i32> -; ALL-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf000 = shufflevector <2 x i32> undef, <2 x i32> undef, <3 x i32> zeroinitializer -; ALL-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf001 = shufflevector <2 x i32> undef, <2 x i32> undef, <3 x i32> -; ALL-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf010 = shufflevector <2 x i32> undef, <2 x i32> undef, <3 x i32> -; ALL-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf011 = shufflevector <2 x i32> undef, <2 x i32> undef, <3 x i32> -; ALL-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf100 = shufflevector <2 x i32> undef, <2 x i32> undef, <3 x i32> -; ALL-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf101 = shufflevector <2 x i32> undef, <2 x i32> undef, <3 x i32> -; ALL-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf110 = shufflevector <2 x i32> undef, <2 x i32> undef, <3 x i32> -; ALL-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf111 = shufflevector <2 x i32> undef, <2 x i32> undef, <3 x i32> -; ALL-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf002 = shufflevector <2 x i32> undef, <2 x i32> undef, <3 x i32> -; ALL-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf020 = shufflevector <2 x i32> undef, <2 x i32> undef, <3 x i32> -; ALL-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf022 = shufflevector <2 x i32> undef, <2 x i32> undef, <3 x i32> -; ALL-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf200 = shufflevector <2 x i32> undef, <2 x i32> undef, <3 x i32> -; ALL-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf202 = shufflevector <2 x i32> undef, <2 x i32> undef, <3 x i32> -; ALL-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf220 = shufflevector <2 x i32> undef, <2 x i32> undef, <3 x i32> -; ALL-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf222 = shufflevector <2 x i32> undef, <2 x i32> undef, <3 x i32> -; ALL-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf112 = shufflevector <2 x i32> undef, <2 x i32> undef, <3 x i32> -; ALL-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf121 = shufflevector <2 x i32> undef, <2 x i32> undef, <3 x i32> -; ALL-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf122 = shufflevector <2 x i32> undef, <2 x i32> undef, <3 x i32> -; ALL-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf211 = shufflevector <2 x i32> undef, <2 x i32> undef, <3 x i32> -; ALL-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf212 = shufflevector <2 x i32> undef, <2 x i32> undef, <3 x i32> -; ALL-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf221 = shufflevector <2 x i32> undef, <2 x i32> undef, <3 x i32> +; ALL-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf00 = shufflevector <2 x i32> %vec1, <2 x i32> %vec1, <2 x i32> zeroinitializer +; ALL-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf01 = shufflevector <2 x i32> %vec1, <2 x i32> %vec1, <2 x i32> +; ALL-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf10 = shufflevector <2 x i32> %vec1, <2 x i32> %vec1, <2 x i32> +; ALL-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf11 = shufflevector <2 x i32> %vec1, <2 x i32> %vec1, <2 x i32> +; ALL-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf02 = shufflevector <2 x i32> %vec1, <2 x i32> %vec1, <2 x i32> +; ALL-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf20 = shufflevector <2 x i32> %vec1, <2 x i32> %vec1, <2 x i32> +; ALL-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf22 = shufflevector <2 x i32> %vec1, <2 x i32> %vec1, <2 x i32> +; ALL-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf03 = shufflevector <2 x i32> %vec1, <2 x i32> %vec1, <2 x i32> +; ALL-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf30 = shufflevector <2 x i32> %vec1, <2 x i32> %vec1, <2 x i32> +; ALL-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf33 = shufflevector <2 x i32> %vec1, <2 x i32> %vec1, <2 x i32> +; ALL-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf12 = shufflevector <2 x i32> %vec1, <2 x i32> %vec1, <2 x i32> +; ALL-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf21 = shufflevector <2 x i32> %vec1, <2 x i32> %vec1, <2 x i32> +; ALL-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf13 = shufflevector <2 x i32> %vec1, <2 x i32> %vec1, <2 x i32> +; ALL-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf31 = shufflevector <2 x i32> %vec1, <2 x i32> %vec1, <2 x i32> +; ALL-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf23 = shufflevector <2 x i32> %vec1, <2 x i32> %vec1, <2 x i32> +; ALL-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf32 = shufflevector <2 x i32> %vec1, <2 x i32> %vec1, <2 x i32> +; ALL-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf000 = shufflevector <2 x i32> %vec1, <2 x i32> %vec1, <3 x i32> zeroinitializer +; ALL-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf001 = shufflevector <2 x i32> %vec1, <2 x i32> %vec1, <3 x i32> +; ALL-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf010 = shufflevector <2 x i32> %vec1, <2 x i32> %vec1, <3 x i32> +; ALL-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf011 = shufflevector <2 x i32> %vec1, <2 x i32> %vec1, <3 x i32> +; ALL-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf100 = shufflevector <2 x i32> %vec1, <2 x i32> %vec1, <3 x i32> +; ALL-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf101 = shufflevector <2 x i32> %vec1, <2 x i32> %vec1, <3 x i32> +; ALL-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf110 = shufflevector <2 x i32> %vec1, <2 x i32> %vec1, <3 x i32> +; ALL-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf111 = shufflevector <2 x i32> %vec1, <2 x i32> %vec1, <3 x i32> +; ALL-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf002 = shufflevector <2 x i32> %vec1, <2 x i32> %vec1, <3 x i32> +; ALL-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf020 = shufflevector <2 x i32> %vec1, <2 x i32> %vec1, <3 x i32> +; ALL-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf022 = shufflevector <2 x i32> %vec1, <2 x i32> %vec1, <3 x i32> +; ALL-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf200 = shufflevector <2 x i32> %vec1, <2 x i32> %vec1, <3 x i32> +; ALL-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf202 = shufflevector <2 x i32> %vec1, <2 x i32> %vec1, <3 x i32> +; ALL-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf220 = shufflevector <2 x i32> %vec1, <2 x i32> %vec1, <3 x i32> +; ALL-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf222 = shufflevector <2 x i32> %vec1, <2 x i32> %vec1, <3 x i32> +; ALL-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf112 = shufflevector <2 x i32> %vec1, <2 x i32> %vec1, <3 x i32> +; ALL-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf121 = shufflevector <2 x i32> %vec1, <2 x i32> %vec1, <3 x i32> +; ALL-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf122 = shufflevector <2 x i32> %vec1, <2 x i32> %vec1, <3 x i32> +; ALL-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf211 = shufflevector <2 x i32> %vec1, <2 x i32> %vec1, <3 x i32> +; ALL-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf212 = shufflevector <2 x i32> %vec1, <2 x i32> %vec1, <3 x i32> +; ALL-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf221 = shufflevector <2 x i32> %vec1, <2 x i32> %vec1, <3 x i32> +; ALL-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf00_2 = shufflevector <2 x i32> %vec1, <2 x i32> %vec2, <2 x i32> zeroinitializer +; ALL-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf01_2 = shufflevector <2 x i32> %vec1, <2 x i32> %vec2, <2 x i32> +; ALL-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf10_2 = shufflevector <2 x i32> %vec1, <2 x i32> %vec2, <2 x i32> +; ALL-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf11_2 = shufflevector <2 x i32> %vec1, <2 x i32> %vec2, <2 x i32> +; ALL-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf02_2 = shufflevector <2 x i32> %vec1, <2 x i32> %vec2, <2 x i32> +; ALL-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf20_2 = shufflevector <2 x i32> %vec1, <2 x i32> %vec2, <2 x i32> +; ALL-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf22_2 = shufflevector <2 x i32> %vec1, <2 x i32> %vec2, <2 x i32> +; ALL-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf03_2 = shufflevector <2 x i32> %vec1, <2 x i32> %vec2, <2 x i32> +; ALL-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf30_2 = shufflevector <2 x i32> %vec1, <2 x i32> %vec2, <2 x i32> +; ALL-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf33_2 = shufflevector <2 x i32> %vec1, <2 x i32> %vec2, <2 x i32> +; ALL-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf12_2 = shufflevector <2 x i32> %vec1, <2 x i32> %vec2, <2 x i32> +; ALL-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf21_2 = shufflevector <2 x i32> %vec1, <2 x i32> %vec2, <2 x i32> +; ALL-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf13_2 = shufflevector <2 x i32> %vec1, <2 x i32> %vec2, <2 x i32> +; ALL-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf31_2 = shufflevector <2 x i32> %vec1, <2 x i32> %vec2, <2 x i32> +; ALL-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf23_2 = shufflevector <2 x i32> %vec1, <2 x i32> %vec2, <2 x i32> +; ALL-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf32_2 = shufflevector <2 x i32> %vec1, <2 x i32> %vec2, <2 x i32> +; ALL-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf000_2 = shufflevector <2 x i32> %vec1, <2 x i32> %vec2, <3 x i32> zeroinitializer +; ALL-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf001_2 = shufflevector <2 x i32> %vec1, <2 x i32> %vec2, <3 x i32> +; ALL-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf010_2 = shufflevector <2 x i32> %vec1, <2 x i32> %vec2, <3 x i32> +; ALL-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf011_2 = shufflevector <2 x i32> %vec1, <2 x i32> %vec2, <3 x i32> +; ALL-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf100_2 = shufflevector <2 x i32> %vec1, <2 x i32> %vec2, <3 x i32> +; ALL-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf101_2 = shufflevector <2 x i32> %vec1, <2 x i32> %vec2, <3 x i32> +; ALL-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf110_2 = shufflevector <2 x i32> %vec1, <2 x i32> %vec2, <3 x i32> +; ALL-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf111_2 = shufflevector <2 x i32> %vec1, <2 x i32> %vec2, <3 x i32> +; ALL-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf002_2 = shufflevector <2 x i32> %vec1, <2 x i32> %vec2, <3 x i32> +; ALL-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf020_2 = shufflevector <2 x i32> %vec1, <2 x i32> %vec2, <3 x i32> +; ALL-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf022_2 = shufflevector <2 x i32> %vec1, <2 x i32> %vec2, <3 x i32> +; ALL-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf200_2 = shufflevector <2 x i32> %vec1, <2 x i32> %vec2, <3 x i32> +; ALL-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf202_2 = shufflevector <2 x i32> %vec1, <2 x i32> %vec2, <3 x i32> +; ALL-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf220_2 = shufflevector <2 x i32> %vec1, <2 x i32> %vec2, <3 x i32> +; ALL-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf222_2 = shufflevector <2 x i32> %vec1, <2 x i32> %vec2, <3 x i32> +; ALL-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf112_2 = shufflevector <2 x i32> %vec1, <2 x i32> %vec2, <3 x i32> +; ALL-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf121_2 = shufflevector <2 x i32> %vec1, <2 x i32> %vec2, <3 x i32> +; ALL-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf122_2 = shufflevector <2 x i32> %vec1, <2 x i32> %vec2, <3 x i32> +; ALL-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf211_2 = shufflevector <2 x i32> %vec1, <2 x i32> %vec2, <3 x i32> +; ALL-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf212_2 = shufflevector <2 x i32> %vec1, <2 x i32> %vec2, <3 x i32> +; ALL-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf221_2 = shufflevector <2 x i32> %vec1, <2 x i32> %vec2, <3 x i32> ; ALL-NEXT: Cost Model: Found an estimated cost of 10 for instruction: ret void ; ; ALL-SIZE-LABEL: 'shufflevector_i32' -; ALL-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf00 = shufflevector <2 x i32> undef, <2 x i32> undef, <2 x i32> zeroinitializer -; ALL-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf01 = shufflevector <2 x i32> undef, <2 x i32> undef, <2 x i32> -; ALL-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf10 = shufflevector <2 x i32> undef, <2 x i32> undef, <2 x i32> -; ALL-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf11 = shufflevector <2 x i32> undef, <2 x i32> undef, <2 x i32> -; ALL-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf02 = shufflevector <2 x i32> undef, <2 x i32> undef, <2 x i32> -; ALL-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf20 = shufflevector <2 x i32> undef, <2 x i32> undef, <2 x i32> -; ALL-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf22 = shufflevector <2 x i32> undef, <2 x i32> undef, <2 x i32> -; ALL-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf03 = shufflevector <2 x i32> undef, <2 x i32> undef, <2 x i32> -; ALL-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf30 = shufflevector <2 x i32> undef, <2 x i32> undef, <2 x i32> -; ALL-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf33 = shufflevector <2 x i32> undef, <2 x i32> undef, <2 x i32> -; ALL-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf12 = shufflevector <2 x i32> undef, <2 x i32> undef, <2 x i32> -; ALL-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf21 = shufflevector <2 x i32> undef, <2 x i32> undef, <2 x i32> -; ALL-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf13 = shufflevector <2 x i32> undef, <2 x i32> undef, <2 x i32> -; ALL-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf31 = shufflevector <2 x i32> undef, <2 x i32> undef, <2 x i32> -; ALL-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf23 = shufflevector <2 x i32> undef, <2 x i32> undef, <2 x i32> -; ALL-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf32 = shufflevector <2 x i32> undef, <2 x i32> undef, <2 x i32> -; ALL-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf000 = shufflevector <2 x i32> undef, <2 x i32> undef, <3 x i32> zeroinitializer -; ALL-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf001 = shufflevector <2 x i32> undef, <2 x i32> undef, <3 x i32> -; ALL-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf010 = shufflevector <2 x i32> undef, <2 x i32> undef, <3 x i32> -; ALL-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf011 = shufflevector <2 x i32> undef, <2 x i32> undef, <3 x i32> -; ALL-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf100 = shufflevector <2 x i32> undef, <2 x i32> undef, <3 x i32> -; ALL-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf101 = shufflevector <2 x i32> undef, <2 x i32> undef, <3 x i32> -; ALL-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf110 = shufflevector <2 x i32> undef, <2 x i32> undef, <3 x i32> -; ALL-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf111 = shufflevector <2 x i32> undef, <2 x i32> undef, <3 x i32> -; ALL-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf002 = shufflevector <2 x i32> undef, <2 x i32> undef, <3 x i32> -; ALL-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf020 = shufflevector <2 x i32> undef, <2 x i32> undef, <3 x i32> -; ALL-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf022 = shufflevector <2 x i32> undef, <2 x i32> undef, <3 x i32> -; ALL-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf200 = shufflevector <2 x i32> undef, <2 x i32> undef, <3 x i32> -; ALL-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf202 = shufflevector <2 x i32> undef, <2 x i32> undef, <3 x i32> -; ALL-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf220 = shufflevector <2 x i32> undef, <2 x i32> undef, <3 x i32> -; ALL-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf222 = shufflevector <2 x i32> undef, <2 x i32> undef, <3 x i32> -; ALL-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf112 = shufflevector <2 x i32> undef, <2 x i32> undef, <3 x i32> -; ALL-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf121 = shufflevector <2 x i32> undef, <2 x i32> undef, <3 x i32> -; ALL-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf122 = shufflevector <2 x i32> undef, <2 x i32> undef, <3 x i32> -; ALL-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf211 = shufflevector <2 x i32> undef, <2 x i32> undef, <3 x i32> -; ALL-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf212 = shufflevector <2 x i32> undef, <2 x i32> undef, <3 x i32> -; ALL-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf221 = shufflevector <2 x i32> undef, <2 x i32> undef, <3 x i32> +; ALL-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf00 = shufflevector <2 x i32> %vec1, <2 x i32> %vec1, <2 x i32> zeroinitializer +; ALL-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf01 = shufflevector <2 x i32> %vec1, <2 x i32> %vec1, <2 x i32> +; ALL-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf10 = shufflevector <2 x i32> %vec1, <2 x i32> %vec1, <2 x i32> +; ALL-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf11 = shufflevector <2 x i32> %vec1, <2 x i32> %vec1, <2 x i32> +; ALL-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf02 = shufflevector <2 x i32> %vec1, <2 x i32> %vec1, <2 x i32> +; ALL-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf20 = shufflevector <2 x i32> %vec1, <2 x i32> %vec1, <2 x i32> +; ALL-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf22 = shufflevector <2 x i32> %vec1, <2 x i32> %vec1, <2 x i32> +; ALL-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf03 = shufflevector <2 x i32> %vec1, <2 x i32> %vec1, <2 x i32> +; ALL-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf30 = shufflevector <2 x i32> %vec1, <2 x i32> %vec1, <2 x i32> +; ALL-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf33 = shufflevector <2 x i32> %vec1, <2 x i32> %vec1, <2 x i32> +; ALL-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf12 = shufflevector <2 x i32> %vec1, <2 x i32> %vec1, <2 x i32> +; ALL-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf21 = shufflevector <2 x i32> %vec1, <2 x i32> %vec1, <2 x i32> +; ALL-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf13 = shufflevector <2 x i32> %vec1, <2 x i32> %vec1, <2 x i32> +; ALL-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf31 = shufflevector <2 x i32> %vec1, <2 x i32> %vec1, <2 x i32> +; ALL-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf23 = shufflevector <2 x i32> %vec1, <2 x i32> %vec1, <2 x i32> +; ALL-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf32 = shufflevector <2 x i32> %vec1, <2 x i32> %vec1, <2 x i32> +; ALL-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf000 = shufflevector <2 x i32> %vec1, <2 x i32> %vec1, <3 x i32> zeroinitializer +; ALL-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf001 = shufflevector <2 x i32> %vec1, <2 x i32> %vec1, <3 x i32> +; ALL-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf010 = shufflevector <2 x i32> %vec1, <2 x i32> %vec1, <3 x i32> +; ALL-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf011 = shufflevector <2 x i32> %vec1, <2 x i32> %vec1, <3 x i32> +; ALL-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf100 = shufflevector <2 x i32> %vec1, <2 x i32> %vec1, <3 x i32> +; ALL-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf101 = shufflevector <2 x i32> %vec1, <2 x i32> %vec1, <3 x i32> +; ALL-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf110 = shufflevector <2 x i32> %vec1, <2 x i32> %vec1, <3 x i32> +; ALL-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf111 = shufflevector <2 x i32> %vec1, <2 x i32> %vec1, <3 x i32> +; ALL-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf002 = shufflevector <2 x i32> %vec1, <2 x i32> %vec1, <3 x i32> +; ALL-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf020 = shufflevector <2 x i32> %vec1, <2 x i32> %vec1, <3 x i32> +; ALL-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf022 = shufflevector <2 x i32> %vec1, <2 x i32> %vec1, <3 x i32> +; ALL-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf200 = shufflevector <2 x i32> %vec1, <2 x i32> %vec1, <3 x i32> +; ALL-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf202 = shufflevector <2 x i32> %vec1, <2 x i32> %vec1, <3 x i32> +; ALL-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf220 = shufflevector <2 x i32> %vec1, <2 x i32> %vec1, <3 x i32> +; ALL-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf222 = shufflevector <2 x i32> %vec1, <2 x i32> %vec1, <3 x i32> +; ALL-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf112 = shufflevector <2 x i32> %vec1, <2 x i32> %vec1, <3 x i32> +; ALL-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf121 = shufflevector <2 x i32> %vec1, <2 x i32> %vec1, <3 x i32> +; ALL-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf122 = shufflevector <2 x i32> %vec1, <2 x i32> %vec1, <3 x i32> +; ALL-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf211 = shufflevector <2 x i32> %vec1, <2 x i32> %vec1, <3 x i32> +; ALL-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf212 = shufflevector <2 x i32> %vec1, <2 x i32> %vec1, <3 x i32> +; ALL-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf221 = shufflevector <2 x i32> %vec1, <2 x i32> %vec1, <3 x i32> +; ALL-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf00_2 = shufflevector <2 x i32> %vec1, <2 x i32> %vec2, <2 x i32> zeroinitializer +; ALL-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf01_2 = shufflevector <2 x i32> %vec1, <2 x i32> %vec2, <2 x i32> +; ALL-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf10_2 = shufflevector <2 x i32> %vec1, <2 x i32> %vec2, <2 x i32> +; ALL-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf11_2 = shufflevector <2 x i32> %vec1, <2 x i32> %vec2, <2 x i32> +; ALL-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf02_2 = shufflevector <2 x i32> %vec1, <2 x i32> %vec2, <2 x i32> +; ALL-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf20_2 = shufflevector <2 x i32> %vec1, <2 x i32> %vec2, <2 x i32> +; ALL-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf22_2 = shufflevector <2 x i32> %vec1, <2 x i32> %vec2, <2 x i32> +; ALL-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf03_2 = shufflevector <2 x i32> %vec1, <2 x i32> %vec2, <2 x i32> +; ALL-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf30_2 = shufflevector <2 x i32> %vec1, <2 x i32> %vec2, <2 x i32> +; ALL-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf33_2 = shufflevector <2 x i32> %vec1, <2 x i32> %vec2, <2 x i32> +; ALL-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf12_2 = shufflevector <2 x i32> %vec1, <2 x i32> %vec2, <2 x i32> +; ALL-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf21_2 = shufflevector <2 x i32> %vec1, <2 x i32> %vec2, <2 x i32> +; ALL-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf13_2 = shufflevector <2 x i32> %vec1, <2 x i32> %vec2, <2 x i32> +; ALL-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf31_2 = shufflevector <2 x i32> %vec1, <2 x i32> %vec2, <2 x i32> +; ALL-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf23_2 = shufflevector <2 x i32> %vec1, <2 x i32> %vec2, <2 x i32> +; ALL-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf32_2 = shufflevector <2 x i32> %vec1, <2 x i32> %vec2, <2 x i32> +; ALL-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf000_2 = shufflevector <2 x i32> %vec1, <2 x i32> %vec2, <3 x i32> zeroinitializer +; ALL-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf001_2 = shufflevector <2 x i32> %vec1, <2 x i32> %vec2, <3 x i32> +; ALL-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf010_2 = shufflevector <2 x i32> %vec1, <2 x i32> %vec2, <3 x i32> +; ALL-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf011_2 = shufflevector <2 x i32> %vec1, <2 x i32> %vec2, <3 x i32> +; ALL-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf100_2 = shufflevector <2 x i32> %vec1, <2 x i32> %vec2, <3 x i32> +; ALL-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf101_2 = shufflevector <2 x i32> %vec1, <2 x i32> %vec2, <3 x i32> +; ALL-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf110_2 = shufflevector <2 x i32> %vec1, <2 x i32> %vec2, <3 x i32> +; ALL-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf111_2 = shufflevector <2 x i32> %vec1, <2 x i32> %vec2, <3 x i32> +; ALL-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf002_2 = shufflevector <2 x i32> %vec1, <2 x i32> %vec2, <3 x i32> +; ALL-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf020_2 = shufflevector <2 x i32> %vec1, <2 x i32> %vec2, <3 x i32> +; ALL-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf022_2 = shufflevector <2 x i32> %vec1, <2 x i32> %vec2, <3 x i32> +; ALL-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf200_2 = shufflevector <2 x i32> %vec1, <2 x i32> %vec2, <3 x i32> +; ALL-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf202_2 = shufflevector <2 x i32> %vec1, <2 x i32> %vec2, <3 x i32> +; ALL-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf220_2 = shufflevector <2 x i32> %vec1, <2 x i32> %vec2, <3 x i32> +; ALL-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf222_2 = shufflevector <2 x i32> %vec1, <2 x i32> %vec2, <3 x i32> +; ALL-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf112_2 = shufflevector <2 x i32> %vec1, <2 x i32> %vec2, <3 x i32> +; ALL-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf121_2 = shufflevector <2 x i32> %vec1, <2 x i32> %vec2, <3 x i32> +; ALL-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf122_2 = shufflevector <2 x i32> %vec1, <2 x i32> %vec2, <3 x i32> +; ALL-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf211_2 = shufflevector <2 x i32> %vec1, <2 x i32> %vec2, <3 x i32> +; ALL-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf212_2 = shufflevector <2 x i32> %vec1, <2 x i32> %vec2, <3 x i32> +; ALL-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %shuf221_2 = shufflevector <2 x i32> %vec1, <2 x i32> %vec2, <3 x i32> ; ALL-SIZE-NEXT: Cost Model: Found an estimated cost of 1 for instruction: ret void ; - %shuf00 = shufflevector <2 x i32> undef, <2 x i32> undef, <2 x i32> zeroinitializer - %shuf01 = shufflevector <2 x i32> undef, <2 x i32> undef, <2 x i32> - %shuf10 = shufflevector <2 x i32> undef, <2 x i32> undef, <2 x i32> - %shuf11 = shufflevector <2 x i32> undef, <2 x i32> undef, <2 x i32> - %shuf02 = shufflevector <2 x i32> undef, <2 x i32> undef, <2 x i32> - %shuf20 = shufflevector <2 x i32> undef, <2 x i32> undef, <2 x i32> - %shuf22 = shufflevector <2 x i32> undef, <2 x i32> undef, <2 x i32> - %shuf03 = shufflevector <2 x i32> undef, <2 x i32> undef, <2 x i32> - %shuf30 = shufflevector <2 x i32> undef, <2 x i32> undef, <2 x i32> - %shuf33 = shufflevector <2 x i32> undef, <2 x i32> undef, <2 x i32> - %shuf12 = shufflevector <2 x i32> undef, <2 x i32> undef, <2 x i32> - %shuf21 = shufflevector <2 x i32> undef, <2 x i32> undef, <2 x i32> - %shuf13 = shufflevector <2 x i32> undef, <2 x i32> undef, <2 x i32> - %shuf31 = shufflevector <2 x i32> undef, <2 x i32> undef, <2 x i32> - %shuf23 = shufflevector <2 x i32> undef, <2 x i32> undef, <2 x i32> - %shuf32 = shufflevector <2 x i32> undef, <2 x i32> undef, <2 x i32> - %shuf000 = shufflevector <2 x i32> undef, <2 x i32> undef, <3 x i32> - %shuf001 = shufflevector <2 x i32> undef, <2 x i32> undef, <3 x i32> - %shuf010 = shufflevector <2 x i32> undef, <2 x i32> undef, <3 x i32> - %shuf011 = shufflevector <2 x i32> undef, <2 x i32> undef, <3 x i32> - %shuf100 = shufflevector <2 x i32> undef, <2 x i32> undef, <3 x i32> - %shuf101 = shufflevector <2 x i32> undef, <2 x i32> undef, <3 x i32> - %shuf110 = shufflevector <2 x i32> undef, <2 x i32> undef, <3 x i32> - %shuf111 = shufflevector <2 x i32> undef, <2 x i32> undef, <3 x i32> - %shuf002 = shufflevector <2 x i32> undef, <2 x i32> undef, <3 x i32> - %shuf020 = shufflevector <2 x i32> undef, <2 x i32> undef, <3 x i32> - %shuf022 = shufflevector <2 x i32> undef, <2 x i32> undef, <3 x i32> - %shuf200 = shufflevector <2 x i32> undef, <2 x i32> undef, <3 x i32> - %shuf202 = shufflevector <2 x i32> undef, <2 x i32> undef, <3 x i32> - %shuf220 = shufflevector <2 x i32> undef, <2 x i32> undef, <3 x i32> - %shuf222 = shufflevector <2 x i32> undef, <2 x i32> undef, <3 x i32> - %shuf112 = shufflevector <2 x i32> undef, <2 x i32> undef, <3 x i32> - %shuf121 = shufflevector <2 x i32> undef, <2 x i32> undef, <3 x i32> - %shuf122 = shufflevector <2 x i32> undef, <2 x i32> undef, <3 x i32> - %shuf211 = shufflevector <2 x i32> undef, <2 x i32> undef, <3 x i32> - %shuf212 = shufflevector <2 x i32> undef, <2 x i32> undef, <3 x i32> - %shuf221 = shufflevector <2 x i32> undef, <2 x i32> undef, <3 x i32> + %shuf00 = shufflevector <2 x i32> %vec1, <2 x i32> %vec1, <2 x i32> zeroinitializer + %shuf01 = shufflevector <2 x i32> %vec1, <2 x i32> %vec1, <2 x i32> + %shuf10 = shufflevector <2 x i32> %vec1, <2 x i32> %vec1, <2 x i32> + %shuf11 = shufflevector <2 x i32> %vec1, <2 x i32> %vec1, <2 x i32> + %shuf02 = shufflevector <2 x i32> %vec1, <2 x i32> %vec1, <2 x i32> + %shuf20 = shufflevector <2 x i32> %vec1, <2 x i32> %vec1, <2 x i32> + %shuf22 = shufflevector <2 x i32> %vec1, <2 x i32> %vec1, <2 x i32> + %shuf03 = shufflevector <2 x i32> %vec1, <2 x i32> %vec1, <2 x i32> + %shuf30 = shufflevector <2 x i32> %vec1, <2 x i32> %vec1, <2 x i32> + %shuf33 = shufflevector <2 x i32> %vec1, <2 x i32> %vec1, <2 x i32> + %shuf12 = shufflevector <2 x i32> %vec1, <2 x i32> %vec1, <2 x i32> + %shuf21 = shufflevector <2 x i32> %vec1, <2 x i32> %vec1, <2 x i32> + %shuf13 = shufflevector <2 x i32> %vec1, <2 x i32> %vec1, <2 x i32> + %shuf31 = shufflevector <2 x i32> %vec1, <2 x i32> %vec1, <2 x i32> + %shuf23 = shufflevector <2 x i32> %vec1, <2 x i32> %vec1, <2 x i32> + %shuf32 = shufflevector <2 x i32> %vec1, <2 x i32> %vec1, <2 x i32> + %shuf000 = shufflevector <2 x i32> %vec1, <2 x i32> %vec1, <3 x i32> + %shuf001 = shufflevector <2 x i32> %vec1, <2 x i32> %vec1, <3 x i32> + %shuf010 = shufflevector <2 x i32> %vec1, <2 x i32> %vec1, <3 x i32> + %shuf011 = shufflevector <2 x i32> %vec1, <2 x i32> %vec1, <3 x i32> + %shuf100 = shufflevector <2 x i32> %vec1, <2 x i32> %vec1, <3 x i32> + %shuf101 = shufflevector <2 x i32> %vec1, <2 x i32> %vec1, <3 x i32> + %shuf110 = shufflevector <2 x i32> %vec1, <2 x i32> %vec1, <3 x i32> + %shuf111 = shufflevector <2 x i32> %vec1, <2 x i32> %vec1, <3 x i32> + %shuf002 = shufflevector <2 x i32> %vec1, <2 x i32> %vec1, <3 x i32> + %shuf020 = shufflevector <2 x i32> %vec1, <2 x i32> %vec1, <3 x i32> + %shuf022 = shufflevector <2 x i32> %vec1, <2 x i32> %vec1, <3 x i32> + %shuf200 = shufflevector <2 x i32> %vec1, <2 x i32> %vec1, <3 x i32> + %shuf202 = shufflevector <2 x i32> %vec1, <2 x i32> %vec1, <3 x i32> + %shuf220 = shufflevector <2 x i32> %vec1, <2 x i32> %vec1, <3 x i32> + %shuf222 = shufflevector <2 x i32> %vec1, <2 x i32> %vec1, <3 x i32> + %shuf112 = shufflevector <2 x i32> %vec1, <2 x i32> %vec1, <3 x i32> + %shuf121 = shufflevector <2 x i32> %vec1, <2 x i32> %vec1, <3 x i32> + %shuf122 = shufflevector <2 x i32> %vec1, <2 x i32> %vec1, <3 x i32> + %shuf211 = shufflevector <2 x i32> %vec1, <2 x i32> %vec1, <3 x i32> + %shuf212 = shufflevector <2 x i32> %vec1, <2 x i32> %vec1, <3 x i32> + %shuf221 = shufflevector <2 x i32> %vec1, <2 x i32> %vec1, <3 x i32> + %shuf00_2 = shufflevector <2 x i32> %vec1, <2 x i32> %vec2, <2 x i32> zeroinitializer + %shuf01_2 = shufflevector <2 x i32> %vec1, <2 x i32> %vec2, <2 x i32> + %shuf10_2 = shufflevector <2 x i32> %vec1, <2 x i32> %vec2, <2 x i32> + %shuf11_2 = shufflevector <2 x i32> %vec1, <2 x i32> %vec2, <2 x i32> + %shuf02_2 = shufflevector <2 x i32> %vec1, <2 x i32> %vec2, <2 x i32> + %shuf20_2 = shufflevector <2 x i32> %vec1, <2 x i32> %vec2, <2 x i32> + %shuf22_2 = shufflevector <2 x i32> %vec1, <2 x i32> %vec2, <2 x i32> + %shuf03_2 = shufflevector <2 x i32> %vec1, <2 x i32> %vec2, <2 x i32> + %shuf30_2 = shufflevector <2 x i32> %vec1, <2 x i32> %vec2, <2 x i32> + %shuf33_2 = shufflevector <2 x i32> %vec1, <2 x i32> %vec2, <2 x i32> + %shuf12_2 = shufflevector <2 x i32> %vec1, <2 x i32> %vec2, <2 x i32> + %shuf21_2 = shufflevector <2 x i32> %vec1, <2 x i32> %vec2, <2 x i32> + %shuf13_2 = shufflevector <2 x i32> %vec1, <2 x i32> %vec2, <2 x i32> + %shuf31_2 = shufflevector <2 x i32> %vec1, <2 x i32> %vec2, <2 x i32> + %shuf23_2 = shufflevector <2 x i32> %vec1, <2 x i32> %vec2, <2 x i32> + %shuf32_2 = shufflevector <2 x i32> %vec1, <2 x i32> %vec2, <2 x i32> + %shuf000_2 = shufflevector <2 x i32> %vec1, <2 x i32> %vec2, <3 x i32> + %shuf001_2 = shufflevector <2 x i32> %vec1, <2 x i32> %vec2, <3 x i32> + %shuf010_2 = shufflevector <2 x i32> %vec1, <2 x i32> %vec2, <3 x i32> + %shuf011_2 = shufflevector <2 x i32> %vec1, <2 x i32> %vec2, <3 x i32> + %shuf100_2 = shufflevector <2 x i32> %vec1, <2 x i32> %vec2, <3 x i32> + %shuf101_2 = shufflevector <2 x i32> %vec1, <2 x i32> %vec2, <3 x i32> + %shuf110_2 = shufflevector <2 x i32> %vec1, <2 x i32> %vec2, <3 x i32> + %shuf111_2 = shufflevector <2 x i32> %vec1, <2 x i32> %vec2, <3 x i32> + %shuf002_2 = shufflevector <2 x i32> %vec1, <2 x i32> %vec2, <3 x i32> + %shuf020_2 = shufflevector <2 x i32> %vec1, <2 x i32> %vec2, <3 x i32> + %shuf022_2 = shufflevector <2 x i32> %vec1, <2 x i32> %vec2, <3 x i32> + %shuf200_2 = shufflevector <2 x i32> %vec1, <2 x i32> %vec2, <3 x i32> + %shuf202_2 = shufflevector <2 x i32> %vec1, <2 x i32> %vec2, <3 x i32> + %shuf220_2 = shufflevector <2 x i32> %vec1, <2 x i32> %vec2, <3 x i32> + %shuf222_2 = shufflevector <2 x i32> %vec1, <2 x i32> %vec2, <3 x i32> + %shuf112_2 = shufflevector <2 x i32> %vec1, <2 x i32> %vec2, <3 x i32> + %shuf121_2 = shufflevector <2 x i32> %vec1, <2 x i32> %vec2, <3 x i32> + %shuf122_2 = shufflevector <2 x i32> %vec1, <2 x i32> %vec2, <3 x i32> + %shuf211_2 = shufflevector <2 x i32> %vec1, <2 x i32> %vec2, <3 x i32> + %shuf212_2 = shufflevector <2 x i32> %vec1, <2 x i32> %vec2, <3 x i32> + %shuf221_2 = shufflevector <2 x i32> %vec1, <2 x i32> %vec2, <3 x i32> ret void } ; Other shuffle cases -define void @shuffle() { +define void @shuffle(<2 x i8> %i8v2, <2 x i8> %i8v2_2, <4 x i8> %i8v4, <4 x i8> %i8v4_2, <6 x i8> %i8v6, <6 x i8> %i8v6_2, <8 x i8> %i8v8, <8 x i8> %i8v8_2, <16 x i8> %i8v16, <16 x i8> %i8v16_2, <2 x i16> %i16v2, <2 x i16> %i16v2_2, <4 x i16> %i16v4, <4 x i16> %i16v4_2, <8 x i16> %i16v8, <8 x i16> %i16v8_2, <2 x i32> %i32v2, <2 x i32> %i32v2_2, <4 x i32> %i32v4, <4 x i32> %i32v4_2, <2 x float> %floatv2, <2 x float> %floatv2_2, <4 x float> %floatv4, <4 x float> %floatv4_2,<2 x i64> %i64v2, <2 x i64> %i64v2_2,<2 x double> %doublev2, <2 x double> %doublev2_2) { ; GFX9-10-LABEL: 'shuffle' -; GFX9-10-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v2i8_2 = shufflevector <2 x i8> undef, <2 x i8> undef, <2 x i32> -; GFX9-10-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v2i8_4 = shufflevector <2 x i8> undef, <2 x i8> undef, <4 x i32> -; GFX9-10-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v4i8_4 = shufflevector <4 x i8> undef, <4 x i8> undef, <4 x i32> -; GFX9-10-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %v2i8_8 = shufflevector <2 x i8> undef, <2 x i8> undef, <8 x i32> -; GFX9-10-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %v4i8_8 = shufflevector <4 x i8> undef, <4 x i8> undef, <8 x i32> -; GFX9-10-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %v6i8_8 = shufflevector <6 x i8> undef, <6 x i8> undef, <8 x i32> -; GFX9-10-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %v8i8_8 = shufflevector <8 x i8> undef, <8 x i8> undef, <8 x i32> -; GFX9-10-NEXT: Cost Model: Found an estimated cost of 32 for instruction: %v16i8_16 = shufflevector <16 x i8> undef, <16 x i8> undef, <16 x i32> -; GFX9-10-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %v2i16_2 = shufflevector <2 x i16> undef, <2 x i16> undef, <2 x i32> -; GFX9-10-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %v4i16_4 = shufflevector <4 x i16> undef, <4 x i16> undef, <4 x i32> -; GFX9-10-NEXT: Cost Model: Found an estimated cost of 14 for instruction: %v8i16_8 = shufflevector <8 x i16> undef, <8 x i16> undef, <8 x i32> -; GFX9-10-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %v2i32_2 = shufflevector <2 x i32> undef, <2 x i32> undef, <2 x i32> -; GFX9-10-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %v4i32_4 = shufflevector <4 x i32> undef, <4 x i32> undef, <4 x i32> -; GFX9-10-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %v2f32_2 = shufflevector <2 x float> undef, <2 x float> undef, <2 x i32> -; GFX9-10-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %v4f32_4 = shufflevector <4 x float> undef, <4 x float> undef, <4 x i32> -; GFX9-10-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %v2i64_2 = shufflevector <2 x i64> undef, <2 x i64> undef, <2 x i32> -; GFX9-10-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %v2f64_2 = shufflevector <2 x double> undef, <2 x double> undef, <2 x i32> +; GFX9-10-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v2i8_2 = shufflevector <2 x i8> %i8v2, <2 x i8> %i8v2, <2 x i32> +; GFX9-10-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v2i8_2_2 = shufflevector <2 x i8> %i8v2, <2 x i8> %i8v2_2, <2 x i32> +; GFX9-10-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v2i8_4 = shufflevector <2 x i8> %i8v2, <2 x i8> %i8v2, <4 x i32> +; GFX9-10-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v2i8_4_2 = shufflevector <2 x i8> %i8v2, <2 x i8> %i8v2_2, <4 x i32> +; GFX9-10-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v4i8_4 = shufflevector <4 x i8> %i8v4, <4 x i8> %i8v4, <4 x i32> +; GFX9-10-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v4i8_4_2 = shufflevector <4 x i8> %i8v4, <4 x i8> %i8v4_2, <4 x i32> +; GFX9-10-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %v2i8_8 = shufflevector <2 x i8> %i8v2, <2 x i8> %i8v2, <8 x i32> +; GFX9-10-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %v2i8_8_2 = shufflevector <2 x i8> %i8v2, <2 x i8> %i8v2_2, <8 x i32> +; GFX9-10-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %v4i8_8 = shufflevector <4 x i8> %i8v4, <4 x i8> %i8v4, <8 x i32> +; GFX9-10-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %v4i8_8_2 = shufflevector <4 x i8> %i8v4, <4 x i8> %i8v4_2, <8 x i32> +; GFX9-10-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %v6i8_8 = shufflevector <6 x i8> %i8v6, <6 x i8> %i8v6, <8 x i32> +; GFX9-10-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %v6i8_8_2 = shufflevector <6 x i8> %i8v6, <6 x i8> %i8v6_2, <8 x i32> +; GFX9-10-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %v8i8_8 = shufflevector <8 x i8> %i8v8, <8 x i8> %i8v8, <8 x i32> +; GFX9-10-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %v8i8_8_2 = shufflevector <8 x i8> %i8v8, <8 x i8> %i8v8_2, <8 x i32> +; GFX9-10-NEXT: Cost Model: Found an estimated cost of 32 for instruction: %v16i8_16 = shufflevector <16 x i8> %i8v16, <16 x i8> %i8v16, <16 x i32> +; GFX9-10-NEXT: Cost Model: Found an estimated cost of 32 for instruction: %v16i8_16_2 = shufflevector <16 x i8> %i8v16, <16 x i8> %i8v16_2, <16 x i32> +; GFX9-10-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %v2i16_2 = shufflevector <2 x i16> %i16v2, <2 x i16> %i16v2, <2 x i32> +; GFX9-10-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %v2i16_2_2 = shufflevector <2 x i16> %i16v2, <2 x i16> %i16v2_2, <2 x i32> +; GFX9-10-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v4i16_4 = shufflevector <4 x i16> %i16v4, <4 x i16> %i16v4, <4 x i32> +; GFX9-10-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v4i16_4_2 = shufflevector <4 x i16> %i16v4, <4 x i16> %i16v4_2, <4 x i32> +; GFX9-10-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v8i16_8 = shufflevector <8 x i16> %i16v8, <8 x i16> %i16v8, <8 x i32> +; GFX9-10-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v8i16_8_2 = shufflevector <8 x i16> %i16v8, <8 x i16> %i16v8_2, <8 x i32> +; GFX9-10-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %v2i32_2 = shufflevector <2 x i32> %i32v2, <2 x i32> %i32v2, <2 x i32> +; GFX9-10-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %v2i32_2_2 = shufflevector <2 x i32> %i32v2, <2 x i32> %i32v2_2, <2 x i32> +; GFX9-10-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %v4i32_4 = shufflevector <4 x i32> %i32v4, <4 x i32> %i32v4, <4 x i32> +; GFX9-10-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %v4i32_4_2 = shufflevector <4 x i32> %i32v4, <4 x i32> %i32v4_2, <4 x i32> +; GFX9-10-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %v2f32_2 = shufflevector <2 x float> %floatv2, <2 x float> %floatv2, <2 x i32> +; GFX9-10-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %v2f32_2_2 = shufflevector <2 x float> %floatv2, <2 x float> %floatv2_2, <2 x i32> +; GFX9-10-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %v4f32_4 = shufflevector <4 x float> %floatv4, <4 x float> %floatv4, <4 x i32> +; GFX9-10-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %v4f32_4_2 = shufflevector <4 x float> %floatv4, <4 x float> %floatv4_2, <4 x i32> +; GFX9-10-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %v2i64_2 = shufflevector <2 x i64> %i64v2, <2 x i64> %i64v2, <2 x i32> +; GFX9-10-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %v2i64_2_2 = shufflevector <2 x i64> %i64v2, <2 x i64> %i64v2_2, <2 x i32> +; GFX9-10-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %v2f64_2 = shufflevector <2 x double> %doublev2, <2 x double> %doublev2, <2 x i32> +; GFX9-10-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %v2f64_2_2 = shufflevector <2 x double> %doublev2, <2 x double> %doublev2_2, <2 x i32> ; GFX9-10-NEXT: Cost Model: Found an estimated cost of 10 for instruction: ret void ; ; VI-LABEL: 'shuffle' -; VI-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v2i8_2 = shufflevector <2 x i8> undef, <2 x i8> undef, <2 x i32> -; VI-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v2i8_4 = shufflevector <2 x i8> undef, <2 x i8> undef, <4 x i32> -; VI-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v4i8_4 = shufflevector <4 x i8> undef, <4 x i8> undef, <4 x i32> -; VI-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %v2i8_8 = shufflevector <2 x i8> undef, <2 x i8> undef, <8 x i32> -; VI-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %v4i8_8 = shufflevector <4 x i8> undef, <4 x i8> undef, <8 x i32> -; VI-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %v6i8_8 = shufflevector <6 x i8> undef, <6 x i8> undef, <8 x i32> -; VI-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %v8i8_8 = shufflevector <8 x i8> undef, <8 x i8> undef, <8 x i32> -; VI-NEXT: Cost Model: Found an estimated cost of 32 for instruction: %v16i8_16 = shufflevector <16 x i8> undef, <16 x i8> undef, <16 x i32> -; VI-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v2i16_2 = shufflevector <2 x i16> undef, <2 x i16> undef, <2 x i32> -; VI-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %v4i16_4 = shufflevector <4 x i16> undef, <4 x i16> undef, <4 x i32> -; VI-NEXT: Cost Model: Found an estimated cost of 14 for instruction: %v8i16_8 = shufflevector <8 x i16> undef, <8 x i16> undef, <8 x i32> -; VI-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %v2i32_2 = shufflevector <2 x i32> undef, <2 x i32> undef, <2 x i32> -; VI-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %v4i32_4 = shufflevector <4 x i32> undef, <4 x i32> undef, <4 x i32> -; VI-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %v2f32_2 = shufflevector <2 x float> undef, <2 x float> undef, <2 x i32> -; VI-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %v4f32_4 = shufflevector <4 x float> undef, <4 x float> undef, <4 x i32> -; VI-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %v2i64_2 = shufflevector <2 x i64> undef, <2 x i64> undef, <2 x i32> -; VI-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %v2f64_2 = shufflevector <2 x double> undef, <2 x double> undef, <2 x i32> +; VI-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v2i8_2 = shufflevector <2 x i8> %i8v2, <2 x i8> %i8v2, <2 x i32> +; VI-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v2i8_2_2 = shufflevector <2 x i8> %i8v2, <2 x i8> %i8v2_2, <2 x i32> +; VI-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v2i8_4 = shufflevector <2 x i8> %i8v2, <2 x i8> %i8v2, <4 x i32> +; VI-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v2i8_4_2 = shufflevector <2 x i8> %i8v2, <2 x i8> %i8v2_2, <4 x i32> +; VI-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v4i8_4 = shufflevector <4 x i8> %i8v4, <4 x i8> %i8v4, <4 x i32> +; VI-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v4i8_4_2 = shufflevector <4 x i8> %i8v4, <4 x i8> %i8v4_2, <4 x i32> +; VI-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %v2i8_8 = shufflevector <2 x i8> %i8v2, <2 x i8> %i8v2, <8 x i32> +; VI-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %v2i8_8_2 = shufflevector <2 x i8> %i8v2, <2 x i8> %i8v2_2, <8 x i32> +; VI-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %v4i8_8 = shufflevector <4 x i8> %i8v4, <4 x i8> %i8v4, <8 x i32> +; VI-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %v4i8_8_2 = shufflevector <4 x i8> %i8v4, <4 x i8> %i8v4_2, <8 x i32> +; VI-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %v6i8_8 = shufflevector <6 x i8> %i8v6, <6 x i8> %i8v6, <8 x i32> +; VI-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %v6i8_8_2 = shufflevector <6 x i8> %i8v6, <6 x i8> %i8v6_2, <8 x i32> +; VI-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %v8i8_8 = shufflevector <8 x i8> %i8v8, <8 x i8> %i8v8, <8 x i32> +; VI-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %v8i8_8_2 = shufflevector <8 x i8> %i8v8, <8 x i8> %i8v8_2, <8 x i32> +; VI-NEXT: Cost Model: Found an estimated cost of 32 for instruction: %v16i8_16 = shufflevector <16 x i8> %i8v16, <16 x i8> %i8v16, <16 x i32> +; VI-NEXT: Cost Model: Found an estimated cost of 32 for instruction: %v16i8_16_2 = shufflevector <16 x i8> %i8v16, <16 x i8> %i8v16_2, <16 x i32> +; VI-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v2i16_2 = shufflevector <2 x i16> %i16v2, <2 x i16> %i16v2, <2 x i32> +; VI-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v2i16_2_2 = shufflevector <2 x i16> %i16v2, <2 x i16> %i16v2_2, <2 x i32> +; VI-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v4i16_4 = shufflevector <4 x i16> %i16v4, <4 x i16> %i16v4, <4 x i32> +; VI-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v4i16_4_2 = shufflevector <4 x i16> %i16v4, <4 x i16> %i16v4_2, <4 x i32> +; VI-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v8i16_8 = shufflevector <8 x i16> %i16v8, <8 x i16> %i16v8, <8 x i32> +; VI-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v8i16_8_2 = shufflevector <8 x i16> %i16v8, <8 x i16> %i16v8_2, <8 x i32> +; VI-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %v2i32_2 = shufflevector <2 x i32> %i32v2, <2 x i32> %i32v2, <2 x i32> +; VI-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %v2i32_2_2 = shufflevector <2 x i32> %i32v2, <2 x i32> %i32v2_2, <2 x i32> +; VI-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %v4i32_4 = shufflevector <4 x i32> %i32v4, <4 x i32> %i32v4, <4 x i32> +; VI-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %v4i32_4_2 = shufflevector <4 x i32> %i32v4, <4 x i32> %i32v4_2, <4 x i32> +; VI-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %v2f32_2 = shufflevector <2 x float> %floatv2, <2 x float> %floatv2, <2 x i32> +; VI-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %v2f32_2_2 = shufflevector <2 x float> %floatv2, <2 x float> %floatv2_2, <2 x i32> +; VI-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %v4f32_4 = shufflevector <4 x float> %floatv4, <4 x float> %floatv4, <4 x i32> +; VI-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %v4f32_4_2 = shufflevector <4 x float> %floatv4, <4 x float> %floatv4_2, <4 x i32> +; VI-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %v2i64_2 = shufflevector <2 x i64> %i64v2, <2 x i64> %i64v2, <2 x i32> +; VI-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %v2i64_2_2 = shufflevector <2 x i64> %i64v2, <2 x i64> %i64v2_2, <2 x i32> +; VI-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %v2f64_2 = shufflevector <2 x double> %doublev2, <2 x double> %doublev2, <2 x i32> +; VI-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %v2f64_2_2 = shufflevector <2 x double> %doublev2, <2 x double> %doublev2_2, <2 x i32> ; VI-NEXT: Cost Model: Found an estimated cost of 10 for instruction: ret void ; ; GFX9-10-SIZE-LABEL: 'shuffle' -; GFX9-10-SIZE-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v2i8_2 = shufflevector <2 x i8> undef, <2 x i8> undef, <2 x i32> -; GFX9-10-SIZE-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v2i8_4 = shufflevector <2 x i8> undef, <2 x i8> undef, <4 x i32> -; GFX9-10-SIZE-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v4i8_4 = shufflevector <4 x i8> undef, <4 x i8> undef, <4 x i32> -; GFX9-10-SIZE-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %v2i8_8 = shufflevector <2 x i8> undef, <2 x i8> undef, <8 x i32> -; GFX9-10-SIZE-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %v4i8_8 = shufflevector <4 x i8> undef, <4 x i8> undef, <8 x i32> -; GFX9-10-SIZE-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %v6i8_8 = shufflevector <6 x i8> undef, <6 x i8> undef, <8 x i32> -; GFX9-10-SIZE-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %v8i8_8 = shufflevector <8 x i8> undef, <8 x i8> undef, <8 x i32> -; GFX9-10-SIZE-NEXT: Cost Model: Found an estimated cost of 32 for instruction: %v16i8_16 = shufflevector <16 x i8> undef, <16 x i8> undef, <16 x i32> -; GFX9-10-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %v2i16_2 = shufflevector <2 x i16> undef, <2 x i16> undef, <2 x i32> -; GFX9-10-SIZE-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %v4i16_4 = shufflevector <4 x i16> undef, <4 x i16> undef, <4 x i32> -; GFX9-10-SIZE-NEXT: Cost Model: Found an estimated cost of 14 for instruction: %v8i16_8 = shufflevector <8 x i16> undef, <8 x i16> undef, <8 x i32> -; GFX9-10-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %v2i32_2 = shufflevector <2 x i32> undef, <2 x i32> undef, <2 x i32> -; GFX9-10-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %v4i32_4 = shufflevector <4 x i32> undef, <4 x i32> undef, <4 x i32> -; GFX9-10-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %v2f32_2 = shufflevector <2 x float> undef, <2 x float> undef, <2 x i32> -; GFX9-10-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %v4f32_4 = shufflevector <4 x float> undef, <4 x float> undef, <4 x i32> -; GFX9-10-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %v2i64_2 = shufflevector <2 x i64> undef, <2 x i64> undef, <2 x i32> -; GFX9-10-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %v2f64_2 = shufflevector <2 x double> undef, <2 x double> undef, <2 x i32> +; GFX9-10-SIZE-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v2i8_2 = shufflevector <2 x i8> %i8v2, <2 x i8> %i8v2, <2 x i32> +; GFX9-10-SIZE-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v2i8_2_2 = shufflevector <2 x i8> %i8v2, <2 x i8> %i8v2_2, <2 x i32> +; GFX9-10-SIZE-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v2i8_4 = shufflevector <2 x i8> %i8v2, <2 x i8> %i8v2, <4 x i32> +; GFX9-10-SIZE-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v2i8_4_2 = shufflevector <2 x i8> %i8v2, <2 x i8> %i8v2_2, <4 x i32> +; GFX9-10-SIZE-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v4i8_4 = shufflevector <4 x i8> %i8v4, <4 x i8> %i8v4, <4 x i32> +; GFX9-10-SIZE-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v4i8_4_2 = shufflevector <4 x i8> %i8v4, <4 x i8> %i8v4_2, <4 x i32> +; GFX9-10-SIZE-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %v2i8_8 = shufflevector <2 x i8> %i8v2, <2 x i8> %i8v2, <8 x i32> +; GFX9-10-SIZE-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %v2i8_8_2 = shufflevector <2 x i8> %i8v2, <2 x i8> %i8v2_2, <8 x i32> +; GFX9-10-SIZE-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %v4i8_8 = shufflevector <4 x i8> %i8v4, <4 x i8> %i8v4, <8 x i32> +; GFX9-10-SIZE-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %v4i8_8_2 = shufflevector <4 x i8> %i8v4, <4 x i8> %i8v4_2, <8 x i32> +; GFX9-10-SIZE-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %v6i8_8 = shufflevector <6 x i8> %i8v6, <6 x i8> %i8v6, <8 x i32> +; GFX9-10-SIZE-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %v6i8_8_2 = shufflevector <6 x i8> %i8v6, <6 x i8> %i8v6_2, <8 x i32> +; GFX9-10-SIZE-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %v8i8_8 = shufflevector <8 x i8> %i8v8, <8 x i8> %i8v8, <8 x i32> +; GFX9-10-SIZE-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %v8i8_8_2 = shufflevector <8 x i8> %i8v8, <8 x i8> %i8v8_2, <8 x i32> +; GFX9-10-SIZE-NEXT: Cost Model: Found an estimated cost of 32 for instruction: %v16i8_16 = shufflevector <16 x i8> %i8v16, <16 x i8> %i8v16, <16 x i32> +; GFX9-10-SIZE-NEXT: Cost Model: Found an estimated cost of 32 for instruction: %v16i8_16_2 = shufflevector <16 x i8> %i8v16, <16 x i8> %i8v16_2, <16 x i32> +; GFX9-10-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %v2i16_2 = shufflevector <2 x i16> %i16v2, <2 x i16> %i16v2, <2 x i32> +; GFX9-10-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %v2i16_2_2 = shufflevector <2 x i16> %i16v2, <2 x i16> %i16v2_2, <2 x i32> +; GFX9-10-SIZE-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v4i16_4 = shufflevector <4 x i16> %i16v4, <4 x i16> %i16v4, <4 x i32> +; GFX9-10-SIZE-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v4i16_4_2 = shufflevector <4 x i16> %i16v4, <4 x i16> %i16v4_2, <4 x i32> +; GFX9-10-SIZE-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v8i16_8 = shufflevector <8 x i16> %i16v8, <8 x i16> %i16v8, <8 x i32> +; GFX9-10-SIZE-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v8i16_8_2 = shufflevector <8 x i16> %i16v8, <8 x i16> %i16v8_2, <8 x i32> +; GFX9-10-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %v2i32_2 = shufflevector <2 x i32> %i32v2, <2 x i32> %i32v2, <2 x i32> +; GFX9-10-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %v2i32_2_2 = shufflevector <2 x i32> %i32v2, <2 x i32> %i32v2_2, <2 x i32> +; GFX9-10-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %v4i32_4 = shufflevector <4 x i32> %i32v4, <4 x i32> %i32v4, <4 x i32> +; GFX9-10-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %v4i32_4_2 = shufflevector <4 x i32> %i32v4, <4 x i32> %i32v4_2, <4 x i32> +; GFX9-10-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %v2f32_2 = shufflevector <2 x float> %floatv2, <2 x float> %floatv2, <2 x i32> +; GFX9-10-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %v2f32_2_2 = shufflevector <2 x float> %floatv2, <2 x float> %floatv2_2, <2 x i32> +; GFX9-10-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %v4f32_4 = shufflevector <4 x float> %floatv4, <4 x float> %floatv4, <4 x i32> +; GFX9-10-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %v4f32_4_2 = shufflevector <4 x float> %floatv4, <4 x float> %floatv4_2, <4 x i32> +; GFX9-10-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %v2i64_2 = shufflevector <2 x i64> %i64v2, <2 x i64> %i64v2, <2 x i32> +; GFX9-10-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %v2i64_2_2 = shufflevector <2 x i64> %i64v2, <2 x i64> %i64v2_2, <2 x i32> +; GFX9-10-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %v2f64_2 = shufflevector <2 x double> %doublev2, <2 x double> %doublev2, <2 x i32> +; GFX9-10-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %v2f64_2_2 = shufflevector <2 x double> %doublev2, <2 x double> %doublev2_2, <2 x i32> ; GFX9-10-SIZE-NEXT: Cost Model: Found an estimated cost of 1 for instruction: ret void ; ; VI-SIZE-LABEL: 'shuffle' -; VI-SIZE-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v2i8_2 = shufflevector <2 x i8> undef, <2 x i8> undef, <2 x i32> -; VI-SIZE-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v2i8_4 = shufflevector <2 x i8> undef, <2 x i8> undef, <4 x i32> -; VI-SIZE-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v4i8_4 = shufflevector <4 x i8> undef, <4 x i8> undef, <4 x i32> -; VI-SIZE-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %v2i8_8 = shufflevector <2 x i8> undef, <2 x i8> undef, <8 x i32> -; VI-SIZE-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %v4i8_8 = shufflevector <4 x i8> undef, <4 x i8> undef, <8 x i32> -; VI-SIZE-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %v6i8_8 = shufflevector <6 x i8> undef, <6 x i8> undef, <8 x i32> -; VI-SIZE-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %v8i8_8 = shufflevector <8 x i8> undef, <8 x i8> undef, <8 x i32> -; VI-SIZE-NEXT: Cost Model: Found an estimated cost of 32 for instruction: %v16i8_16 = shufflevector <16 x i8> undef, <16 x i8> undef, <16 x i32> -; VI-SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v2i16_2 = shufflevector <2 x i16> undef, <2 x i16> undef, <2 x i32> -; VI-SIZE-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %v4i16_4 = shufflevector <4 x i16> undef, <4 x i16> undef, <4 x i32> -; VI-SIZE-NEXT: Cost Model: Found an estimated cost of 14 for instruction: %v8i16_8 = shufflevector <8 x i16> undef, <8 x i16> undef, <8 x i32> -; VI-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %v2i32_2 = shufflevector <2 x i32> undef, <2 x i32> undef, <2 x i32> -; VI-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %v4i32_4 = shufflevector <4 x i32> undef, <4 x i32> undef, <4 x i32> -; VI-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %v2f32_2 = shufflevector <2 x float> undef, <2 x float> undef, <2 x i32> -; VI-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %v4f32_4 = shufflevector <4 x float> undef, <4 x float> undef, <4 x i32> -; VI-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %v2i64_2 = shufflevector <2 x i64> undef, <2 x i64> undef, <2 x i32> -; VI-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %v2f64_2 = shufflevector <2 x double> undef, <2 x double> undef, <2 x i32> +; VI-SIZE-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v2i8_2 = shufflevector <2 x i8> %i8v2, <2 x i8> %i8v2, <2 x i32> +; VI-SIZE-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v2i8_2_2 = shufflevector <2 x i8> %i8v2, <2 x i8> %i8v2_2, <2 x i32> +; VI-SIZE-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v2i8_4 = shufflevector <2 x i8> %i8v2, <2 x i8> %i8v2, <4 x i32> +; VI-SIZE-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v2i8_4_2 = shufflevector <2 x i8> %i8v2, <2 x i8> %i8v2_2, <4 x i32> +; VI-SIZE-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v4i8_4 = shufflevector <4 x i8> %i8v4, <4 x i8> %i8v4, <4 x i32> +; VI-SIZE-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v4i8_4_2 = shufflevector <4 x i8> %i8v4, <4 x i8> %i8v4_2, <4 x i32> +; VI-SIZE-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %v2i8_8 = shufflevector <2 x i8> %i8v2, <2 x i8> %i8v2, <8 x i32> +; VI-SIZE-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %v2i8_8_2 = shufflevector <2 x i8> %i8v2, <2 x i8> %i8v2_2, <8 x i32> +; VI-SIZE-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %v4i8_8 = shufflevector <4 x i8> %i8v4, <4 x i8> %i8v4, <8 x i32> +; VI-SIZE-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %v4i8_8_2 = shufflevector <4 x i8> %i8v4, <4 x i8> %i8v4_2, <8 x i32> +; VI-SIZE-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %v6i8_8 = shufflevector <6 x i8> %i8v6, <6 x i8> %i8v6, <8 x i32> +; VI-SIZE-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %v6i8_8_2 = shufflevector <6 x i8> %i8v6, <6 x i8> %i8v6_2, <8 x i32> +; VI-SIZE-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %v8i8_8 = shufflevector <8 x i8> %i8v8, <8 x i8> %i8v8, <8 x i32> +; VI-SIZE-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %v8i8_8_2 = shufflevector <8 x i8> %i8v8, <8 x i8> %i8v8_2, <8 x i32> +; VI-SIZE-NEXT: Cost Model: Found an estimated cost of 32 for instruction: %v16i8_16 = shufflevector <16 x i8> %i8v16, <16 x i8> %i8v16, <16 x i32> +; VI-SIZE-NEXT: Cost Model: Found an estimated cost of 32 for instruction: %v16i8_16_2 = shufflevector <16 x i8> %i8v16, <16 x i8> %i8v16_2, <16 x i32> +; VI-SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v2i16_2 = shufflevector <2 x i16> %i16v2, <2 x i16> %i16v2, <2 x i32> +; VI-SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v2i16_2_2 = shufflevector <2 x i16> %i16v2, <2 x i16> %i16v2_2, <2 x i32> +; VI-SIZE-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v4i16_4 = shufflevector <4 x i16> %i16v4, <4 x i16> %i16v4, <4 x i32> +; VI-SIZE-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v4i16_4_2 = shufflevector <4 x i16> %i16v4, <4 x i16> %i16v4_2, <4 x i32> +; VI-SIZE-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v8i16_8 = shufflevector <8 x i16> %i16v8, <8 x i16> %i16v8, <8 x i32> +; VI-SIZE-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v8i16_8_2 = shufflevector <8 x i16> %i16v8, <8 x i16> %i16v8_2, <8 x i32> +; VI-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %v2i32_2 = shufflevector <2 x i32> %i32v2, <2 x i32> %i32v2, <2 x i32> +; VI-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %v2i32_2_2 = shufflevector <2 x i32> %i32v2, <2 x i32> %i32v2_2, <2 x i32> +; VI-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %v4i32_4 = shufflevector <4 x i32> %i32v4, <4 x i32> %i32v4, <4 x i32> +; VI-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %v4i32_4_2 = shufflevector <4 x i32> %i32v4, <4 x i32> %i32v4_2, <4 x i32> +; VI-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %v2f32_2 = shufflevector <2 x float> %floatv2, <2 x float> %floatv2, <2 x i32> +; VI-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %v2f32_2_2 = shufflevector <2 x float> %floatv2, <2 x float> %floatv2_2, <2 x i32> +; VI-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %v4f32_4 = shufflevector <4 x float> %floatv4, <4 x float> %floatv4, <4 x i32> +; VI-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %v4f32_4_2 = shufflevector <4 x float> %floatv4, <4 x float> %floatv4_2, <4 x i32> +; VI-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %v2i64_2 = shufflevector <2 x i64> %i64v2, <2 x i64> %i64v2, <2 x i32> +; VI-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %v2i64_2_2 = shufflevector <2 x i64> %i64v2, <2 x i64> %i64v2_2, <2 x i32> +; VI-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %v2f64_2 = shufflevector <2 x double> %doublev2, <2 x double> %doublev2, <2 x i32> +; VI-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %v2f64_2_2 = shufflevector <2 x double> %doublev2, <2 x double> %doublev2_2, <2 x i32> ; VI-SIZE-NEXT: Cost Model: Found an estimated cost of 1 for instruction: ret void ; - %v2i8_2 = shufflevector <2 x i8> undef, <2 x i8> undef, <2 x i32> - %v2i8_4 = shufflevector <2 x i8> undef, <2 x i8> undef, <4 x i32> - %v4i8_4 = shufflevector <4 x i8> undef, <4 x i8> undef, <4 x i32> - %v2i8_8 = shufflevector <2 x i8> undef, <2 x i8> undef, <8 x i32> - %v4i8_8 = shufflevector <4 x i8> undef, <4 x i8> undef, <8 x i32> - %v6i8_8 = shufflevector <6 x i8> undef, <6 x i8> undef, <8 x i32> - %v8i8_8 = shufflevector <8 x i8> undef, <8 x i8> undef, <8 x i32> - %v16i8_16 = shufflevector <16 x i8> undef, <16 x i8> undef, <16 x i32> - %v2i16_2 = shufflevector <2 x i16> undef, <2 x i16> undef, <2 x i32> - %v4i16_4 = shufflevector <4 x i16> undef, <4 x i16> undef, <4 x i32> - %v8i16_8 = shufflevector <8 x i16> undef, <8 x i16> undef, <8 x i32> - %v2i32_2 = shufflevector <2 x i32> undef, <2 x i32> undef, <2 x i32> - %v4i32_4 = shufflevector <4 x i32> undef, <4 x i32> undef, <4 x i32> - %v2f32_2 = shufflevector <2 x float> undef, <2 x float> undef, <2 x i32> - %v4f32_4 = shufflevector <4 x float> undef, <4 x float> undef, <4 x i32> - %v2i64_2 = shufflevector <2 x i64> undef, <2 x i64> undef, <2 x i32> - %v2f64_2 = shufflevector <2 x double> undef, <2 x double> undef, <2 x i32> + %v2i8_2 = shufflevector <2 x i8> %i8v2, <2 x i8> %i8v2, <2 x i32> + %v2i8_2_2 = shufflevector <2 x i8> %i8v2, <2 x i8> %i8v2_2, <2 x i32> + %v2i8_4 = shufflevector <2 x i8> %i8v2, <2 x i8> %i8v2, <4 x i32> + %v2i8_4_2 = shufflevector <2 x i8> %i8v2, <2 x i8> %i8v2_2, <4 x i32> + %v4i8_4 = shufflevector <4 x i8> %i8v4, <4 x i8> %i8v4, <4 x i32> + %v4i8_4_2 = shufflevector <4 x i8> %i8v4, <4 x i8> %i8v4_2, <4 x i32> + %v2i8_8 = shufflevector <2 x i8> %i8v2, <2 x i8> %i8v2, <8 x i32> + %v2i8_8_2 = shufflevector <2 x i8> %i8v2, <2 x i8> %i8v2_2, <8 x i32> + %v4i8_8 = shufflevector <4 x i8> %i8v4, <4 x i8> %i8v4, <8 x i32> + %v4i8_8_2 = shufflevector <4 x i8> %i8v4, <4 x i8> %i8v4_2, <8 x i32> + %v6i8_8 = shufflevector <6 x i8> %i8v6, <6 x i8> %i8v6, <8 x i32> + %v6i8_8_2 = shufflevector <6 x i8> %i8v6, <6 x i8> %i8v6_2, <8 x i32> + %v8i8_8 = shufflevector <8 x i8> %i8v8, <8 x i8> %i8v8, <8 x i32> + %v8i8_8_2 = shufflevector <8 x i8> %i8v8, <8 x i8> %i8v8_2, <8 x i32> + %v16i8_16 = shufflevector <16 x i8> %i8v16, <16 x i8> %i8v16, <16 x i32> + %v16i8_16_2 = shufflevector <16 x i8> %i8v16, <16 x i8> %i8v16_2, <16 x i32> + %v2i16_2 = shufflevector <2 x i16> %i16v2, <2 x i16> %i16v2, <2 x i32> + %v2i16_2_2 = shufflevector <2 x i16> %i16v2, <2 x i16> %i16v2_2, <2 x i32> + %v4i16_4 = shufflevector <4 x i16> %i16v4, <4 x i16> %i16v4, <4 x i32> + %v4i16_4_2 = shufflevector <4 x i16> %i16v4, <4 x i16> %i16v4_2, <4 x i32> + %v8i16_8 = shufflevector <8 x i16> %i16v8, <8 x i16> %i16v8, <8 x i32> + %v8i16_8_2 = shufflevector <8 x i16> %i16v8, <8 x i16> %i16v8_2, <8 x i32> + %v2i32_2 = shufflevector <2 x i32> %i32v2, <2 x i32> %i32v2, <2 x i32> + %v2i32_2_2 = shufflevector <2 x i32> %i32v2, <2 x i32> %i32v2_2, <2 x i32> + %v4i32_4 = shufflevector <4 x i32> %i32v4, <4 x i32> %i32v4, <4 x i32> + %v4i32_4_2 = shufflevector <4 x i32> %i32v4, <4 x i32> %i32v4_2, <4 x i32> + %v2f32_2 = shufflevector <2 x float> %floatv2, <2 x float> %floatv2, <2 x i32> + %v2f32_2_2 = shufflevector <2 x float> %floatv2, <2 x float> %floatv2_2, <2 x i32> + %v4f32_4 = shufflevector <4 x float> %floatv4, <4 x float> %floatv4, <4 x i32> + %v4f32_4_2 = shufflevector <4 x float> %floatv4, <4 x float> %floatv4_2, <4 x i32> + %v2i64_2 = shufflevector <2 x i64> %i64v2, <2 x i64> %i64v2, <2 x i32> + %v2i64_2_2 = shufflevector <2 x i64> %i64v2, <2 x i64> %i64v2_2, <2 x i32> + %v2f64_2 = shufflevector <2 x double> %doublev2, <2 x double> %doublev2, <2 x i32> + %v2f64_2_2 = shufflevector <2 x double> %doublev2, <2 x double> %doublev2_2, <2 x i32> ret void } -define void @concat() { +define void @concat(<2 x i8> %i8v2, <2 x i8> %i8v2_2, <4 x i8> %i8v4, <4 x i8> %i8v4_2, <8 x i8> %i8v8, <8 x i8> %i8v8_2, <2 x half> %halfv2, <2 x half> %halfv2_2, <4 x half> %halfv4, <4 x half> %halfv4_2, <8 x half> %halfv8, <8 x half> %halfv8_2, <2 x i16> %i16v2, <2 x i16> %i16v2_2, <4 x i16> %i16v4, <4 x i16> %i16v4_2, <8 x i16> %i16v8, <8 x i16> %i16v8_2, <2 x i32> %i32v2, <2 x i32> %i32v2_2, <4 x i32> %i32v4, <4 x i32> %i32v4_2, <2 x float> %floatv2, <2 x float> %floatv2_2, <4 x float> %floatv4, <4 x float> %floatv4_2,<2 x i64> %i64v2, <2 x i64> %i64v2_2,<2 x double> %doublev2, <2 x double> %doublev2_2) { ; ALL-LABEL: 'concat' -; ALL-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v4i8 = shufflevector <2 x i8> undef, <2 x i8> undef, <4 x i32> -; ALL-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v8i8 = shufflevector <4 x i8> undef, <4 x i8> undef, <8 x i32> -; ALL-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %v16i8 = shufflevector <8 x i8> undef, <8 x i8> undef, <16 x i32> -; ALL-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v4i16 = shufflevector <2 x i16> undef, <2 x i16> undef, <4 x i32> -; ALL-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %v8i16 = shufflevector <4 x i16> undef, <4 x i16> undef, <8 x i32> -; ALL-NEXT: Cost Model: Found an estimated cost of 15 for instruction: %v16i16 = shufflevector <8 x i16> undef, <8 x i16> undef, <16 x i32> -; ALL-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %v4i32 = shufflevector <2 x i32> undef, <2 x i32> undef, <4 x i32> -; ALL-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %v8i32 = shufflevector <4 x i32> undef, <4 x i32> undef, <8 x i32> -; ALL-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %v4i64 = shufflevector <2 x i64> undef, <2 x i64> undef, <4 x i32> -; ALL-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v4f16 = shufflevector <2 x half> undef, <2 x half> undef, <4 x i32> -; ALL-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %v8f16 = shufflevector <4 x half> undef, <4 x half> undef, <8 x i32> -; ALL-NEXT: Cost Model: Found an estimated cost of 15 for instruction: %v16f16 = shufflevector <8 x half> undef, <8 x half> undef, <16 x i32> -; ALL-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %v4f32 = shufflevector <2 x float> undef, <2 x float> undef, <4 x i32> -; ALL-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %v8f32 = shufflevector <4 x float> undef, <4 x float> undef, <8 x i32> -; ALL-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %v4f64 = shufflevector <2 x double> undef, <2 x double> undef, <4 x i32> +; ALL-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v4i8 = shufflevector <2 x i8> %i8v2, <2 x i8> %i8v2, <4 x i32> +; ALL-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v8i8 = shufflevector <4 x i8> %i8v4, <4 x i8> %i8v4, <8 x i32> +; ALL-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %v16i8 = shufflevector <8 x i8> %i8v8, <8 x i8> %i8v8, <16 x i32> +; ALL-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %v4i16 = shufflevector <2 x i16> %i16v2, <2 x i16> %i16v2, <4 x i32> +; ALL-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %v8i16 = shufflevector <4 x i16> %i16v4, <4 x i16> %i16v4, <8 x i32> +; ALL-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %v16i16 = shufflevector <8 x i16> %i16v8, <8 x i16> %i16v8, <16 x i32> +; ALL-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %v4i32 = shufflevector <2 x i32> %i32v2, <2 x i32> %i32v2, <4 x i32> +; ALL-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %v8i32 = shufflevector <4 x i32> %i32v4, <4 x i32> %i32v4, <8 x i32> +; ALL-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %v4i64 = shufflevector <2 x i64> %i64v2, <2 x i64> %i64v2, <4 x i32> +; ALL-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %v4f16 = shufflevector <2 x half> %halfv2, <2 x half> %halfv2, <4 x i32> +; ALL-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %v8f16 = shufflevector <4 x half> %halfv4, <4 x half> %halfv4, <8 x i32> +; ALL-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %v16f16 = shufflevector <8 x half> %halfv8, <8 x half> %halfv8, <16 x i32> +; ALL-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %v4f32 = shufflevector <2 x float> %floatv2, <2 x float> %floatv2, <4 x i32> +; ALL-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %v8f32 = shufflevector <4 x float> %floatv4, <4 x float> %floatv4, <8 x i32> +; ALL-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %v4f64 = shufflevector <2 x double> %doublev2, <2 x double> %doublev2, <4 x i32> +; ALL-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v4i8_2 = shufflevector <2 x i8> %i8v2, <2 x i8> %i8v2_2, <4 x i32> +; ALL-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v8i8_2 = shufflevector <4 x i8> %i8v4, <4 x i8> %i8v4_2, <8 x i32> +; ALL-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %v16i8_2 = shufflevector <8 x i8> %i8v8, <8 x i8> %i8v8_2, <16 x i32> +; ALL-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %v4i16_2 = shufflevector <2 x i16> %i16v2, <2 x i16> %i16v2_2, <4 x i32> +; ALL-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %v8i16_2 = shufflevector <4 x i16> %i16v4, <4 x i16> %i16v4_2, <8 x i32> +; ALL-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %v16i16_2 = shufflevector <8 x i16> %i16v8, <8 x i16> %i16v8_2, <16 x i32> +; ALL-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %v4i32_2 = shufflevector <2 x i32> %i32v2, <2 x i32> %i32v2_2, <4 x i32> +; ALL-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %v8i32_2 = shufflevector <4 x i32> %i32v4, <4 x i32> %i32v4_2, <8 x i32> +; ALL-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %v4i64_2 = shufflevector <2 x i64> %i64v2, <2 x i64> %i64v2_2, <4 x i32> +; ALL-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %v4f16_2 = shufflevector <2 x half> %halfv2, <2 x half> %halfv2_2, <4 x i32> +; ALL-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %v8f16_2 = shufflevector <4 x half> %halfv4, <4 x half> %halfv4_2, <8 x i32> +; ALL-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %v16f16_2 = shufflevector <8 x half> %halfv8, <8 x half> %halfv8_2, <16 x i32> +; ALL-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %v4f32_2 = shufflevector <2 x float> %floatv2, <2 x float> %floatv2_2, <4 x i32> +; ALL-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %v8f32_2 = shufflevector <4 x float> %floatv4, <4 x float> %floatv4_2, <8 x i32> +; ALL-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %v4f64_2 = shufflevector <2 x double> %doublev2, <2 x double> %doublev2_2, <4 x i32> ; ALL-NEXT: Cost Model: Found an estimated cost of 10 for instruction: ret void ; ; ALL-SIZE-LABEL: 'concat' -; ALL-SIZE-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v4i8 = shufflevector <2 x i8> undef, <2 x i8> undef, <4 x i32> -; ALL-SIZE-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v8i8 = shufflevector <4 x i8> undef, <4 x i8> undef, <8 x i32> -; ALL-SIZE-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %v16i8 = shufflevector <8 x i8> undef, <8 x i8> undef, <16 x i32> -; ALL-SIZE-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v4i16 = shufflevector <2 x i16> undef, <2 x i16> undef, <4 x i32> -; ALL-SIZE-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %v8i16 = shufflevector <4 x i16> undef, <4 x i16> undef, <8 x i32> -; ALL-SIZE-NEXT: Cost Model: Found an estimated cost of 15 for instruction: %v16i16 = shufflevector <8 x i16> undef, <8 x i16> undef, <16 x i32> -; ALL-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %v4i32 = shufflevector <2 x i32> undef, <2 x i32> undef, <4 x i32> -; ALL-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %v8i32 = shufflevector <4 x i32> undef, <4 x i32> undef, <8 x i32> -; ALL-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %v4i64 = shufflevector <2 x i64> undef, <2 x i64> undef, <4 x i32> -; ALL-SIZE-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v4f16 = shufflevector <2 x half> undef, <2 x half> undef, <4 x i32> -; ALL-SIZE-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %v8f16 = shufflevector <4 x half> undef, <4 x half> undef, <8 x i32> -; ALL-SIZE-NEXT: Cost Model: Found an estimated cost of 15 for instruction: %v16f16 = shufflevector <8 x half> undef, <8 x half> undef, <16 x i32> -; ALL-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %v4f32 = shufflevector <2 x float> undef, <2 x float> undef, <4 x i32> -; ALL-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %v8f32 = shufflevector <4 x float> undef, <4 x float> undef, <8 x i32> -; ALL-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %v4f64 = shufflevector <2 x double> undef, <2 x double> undef, <4 x i32> +; ALL-SIZE-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v4i8 = shufflevector <2 x i8> %i8v2, <2 x i8> %i8v2, <4 x i32> +; ALL-SIZE-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v8i8 = shufflevector <4 x i8> %i8v4, <4 x i8> %i8v4, <8 x i32> +; ALL-SIZE-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %v16i8 = shufflevector <8 x i8> %i8v8, <8 x i8> %i8v8, <16 x i32> +; ALL-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %v4i16 = shufflevector <2 x i16> %i16v2, <2 x i16> %i16v2, <4 x i32> +; ALL-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %v8i16 = shufflevector <4 x i16> %i16v4, <4 x i16> %i16v4, <8 x i32> +; ALL-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %v16i16 = shufflevector <8 x i16> %i16v8, <8 x i16> %i16v8, <16 x i32> +; ALL-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %v4i32 = shufflevector <2 x i32> %i32v2, <2 x i32> %i32v2, <4 x i32> +; ALL-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %v8i32 = shufflevector <4 x i32> %i32v4, <4 x i32> %i32v4, <8 x i32> +; ALL-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %v4i64 = shufflevector <2 x i64> %i64v2, <2 x i64> %i64v2, <4 x i32> +; ALL-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %v4f16 = shufflevector <2 x half> %halfv2, <2 x half> %halfv2, <4 x i32> +; ALL-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %v8f16 = shufflevector <4 x half> %halfv4, <4 x half> %halfv4, <8 x i32> +; ALL-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %v16f16 = shufflevector <8 x half> %halfv8, <8 x half> %halfv8, <16 x i32> +; ALL-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %v4f32 = shufflevector <2 x float> %floatv2, <2 x float> %floatv2, <4 x i32> +; ALL-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %v8f32 = shufflevector <4 x float> %floatv4, <4 x float> %floatv4, <8 x i32> +; ALL-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %v4f64 = shufflevector <2 x double> %doublev2, <2 x double> %doublev2, <4 x i32> +; ALL-SIZE-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v4i8_2 = shufflevector <2 x i8> %i8v2, <2 x i8> %i8v2_2, <4 x i32> +; ALL-SIZE-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v8i8_2 = shufflevector <4 x i8> %i8v4, <4 x i8> %i8v4_2, <8 x i32> +; ALL-SIZE-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %v16i8_2 = shufflevector <8 x i8> %i8v8, <8 x i8> %i8v8_2, <16 x i32> +; ALL-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %v4i16_2 = shufflevector <2 x i16> %i16v2, <2 x i16> %i16v2_2, <4 x i32> +; ALL-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %v8i16_2 = shufflevector <4 x i16> %i16v4, <4 x i16> %i16v4_2, <8 x i32> +; ALL-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %v16i16_2 = shufflevector <8 x i16> %i16v8, <8 x i16> %i16v8_2, <16 x i32> +; ALL-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %v4i32_2 = shufflevector <2 x i32> %i32v2, <2 x i32> %i32v2_2, <4 x i32> +; ALL-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %v8i32_2 = shufflevector <4 x i32> %i32v4, <4 x i32> %i32v4_2, <8 x i32> +; ALL-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %v4i64_2 = shufflevector <2 x i64> %i64v2, <2 x i64> %i64v2_2, <4 x i32> +; ALL-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %v4f16_2 = shufflevector <2 x half> %halfv2, <2 x half> %halfv2_2, <4 x i32> +; ALL-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %v8f16_2 = shufflevector <4 x half> %halfv4, <4 x half> %halfv4_2, <8 x i32> +; ALL-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %v16f16_2 = shufflevector <8 x half> %halfv8, <8 x half> %halfv8_2, <16 x i32> +; ALL-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %v4f32_2 = shufflevector <2 x float> %floatv2, <2 x float> %floatv2_2, <4 x i32> +; ALL-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %v8f32_2 = shufflevector <4 x float> %floatv4, <4 x float> %floatv4_2, <8 x i32> +; ALL-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %v4f64_2 = shufflevector <2 x double> %doublev2, <2 x double> %doublev2_2, <4 x i32> ; ALL-SIZE-NEXT: Cost Model: Found an estimated cost of 1 for instruction: ret void ; - %v4i8 = shufflevector <2 x i8> undef, <2 x i8> undef, <4 x i32> - %v8i8 = shufflevector <4 x i8> undef, <4 x i8> undef, <8 x i32> - %v16i8 = shufflevector <8 x i8> undef, <8 x i8> undef, <16 x i32> - %v4i16 = shufflevector <2 x i16> undef, <2 x i16> undef, <4 x i32> - %v8i16 = shufflevector <4 x i16> undef, <4 x i16> undef, <8 x i32> - %v16i16 = shufflevector <8 x i16> undef, <8 x i16> undef, <16 x i32> - %v4i32 = shufflevector <2 x i32> undef, <2 x i32> undef, <4 x i32> - %v8i32 = shufflevector <4 x i32> undef, <4 x i32> undef, <8 x i32> - %v4i64 = shufflevector <2 x i64> undef, <2 x i64> undef, <4 x i32> - %v4f16 = shufflevector <2 x half> undef, <2 x half> undef, <4 x i32> - %v8f16 = shufflevector <4 x half> undef, <4 x half> undef, <8 x i32> - %v16f16 = shufflevector <8 x half> undef, <8 x half> undef, <16 x i32> - %v4f32 = shufflevector <2 x float> undef, <2 x float> undef, <4 x i32> - %v8f32 = shufflevector <4 x float> undef, <4 x float> undef, <8 x i32> - %v4f64 = shufflevector <2 x double> undef, <2 x double> undef, <4 x i32> + %v4i8 = shufflevector <2 x i8> %i8v2, <2 x i8> %i8v2, <4 x i32> + %v8i8 = shufflevector <4 x i8> %i8v4, <4 x i8> %i8v4, <8 x i32> + %v16i8 = shufflevector <8 x i8> %i8v8, <8 x i8> %i8v8, <16 x i32> + %v4i16 = shufflevector <2 x i16> %i16v2, <2 x i16> %i16v2, <4 x i32> + %v8i16 = shufflevector <4 x i16> %i16v4, <4 x i16> %i16v4, <8 x i32> + %v16i16 = shufflevector <8 x i16> %i16v8, <8 x i16> %i16v8, <16 x i32> + %v4i32 = shufflevector <2 x i32> %i32v2, <2 x i32> %i32v2, <4 x i32> + %v8i32 = shufflevector <4 x i32> %i32v4, <4 x i32> %i32v4, <8 x i32> + %v4i64 = shufflevector <2 x i64> %i64v2, <2 x i64> %i64v2, <4 x i32> + %v4f16 = shufflevector <2 x half> %halfv2, <2 x half> %halfv2, <4 x i32> + %v8f16 = shufflevector <4 x half> %halfv4, <4 x half> %halfv4, <8 x i32> + %v16f16 = shufflevector <8 x half> %halfv8, <8 x half> %halfv8, <16 x i32> + %v4f32 = shufflevector <2 x float> %floatv2, <2 x float> %floatv2, <4 x i32> + %v8f32 = shufflevector <4 x float> %floatv4, <4 x float> %floatv4, <8 x i32> + %v4f64 = shufflevector <2 x double> %doublev2, <2 x double> %doublev2, <4 x i32> + %v4i8_2 = shufflevector <2 x i8> %i8v2, <2 x i8> %i8v2_2, <4 x i32> + %v8i8_2 = shufflevector <4 x i8> %i8v4, <4 x i8> %i8v4_2, <8 x i32> + %v16i8_2 = shufflevector <8 x i8> %i8v8, <8 x i8> %i8v8_2, <16 x i32> + %v4i16_2 = shufflevector <2 x i16> %i16v2, <2 x i16> %i16v2_2, <4 x i32> + %v8i16_2 = shufflevector <4 x i16> %i16v4, <4 x i16> %i16v4_2, <8 x i32> + %v16i16_2 = shufflevector <8 x i16> %i16v8, <8 x i16> %i16v8_2, <16 x i32> + %v4i32_2 = shufflevector <2 x i32> %i32v2, <2 x i32> %i32v2_2, <4 x i32> + %v8i32_2 = shufflevector <4 x i32> %i32v4, <4 x i32> %i32v4_2, <8 x i32> + %v4i64_2 = shufflevector <2 x i64> %i64v2, <2 x i64> %i64v2_2, <4 x i32> + %v4f16_2 = shufflevector <2 x half> %halfv2, <2 x half> %halfv2_2, <4 x i32> + %v8f16_2 = shufflevector <4 x half> %halfv4, <4 x half> %halfv4_2, <8 x i32> + %v16f16_2 = shufflevector <8 x half> %halfv8, <8 x half> %halfv8_2, <16 x i32> + %v4f32_2 = shufflevector <2 x float> %floatv2, <2 x float> %floatv2_2, <4 x i32> + %v8f32_2 = shufflevector <4 x float> %floatv4, <4 x float> %floatv4_2, <8 x i32> + %v4f64_2 = shufflevector <2 x double> %doublev2, <2 x double> %doublev2_2, <4 x i32> ret void } diff --git a/llvm/test/Transforms/SLPVectorizer/AMDGPU/add_sub_sat-inseltpoison.ll b/llvm/test/Transforms/SLPVectorizer/AMDGPU/add_sub_sat-inseltpoison.ll index 290560151b79..3749bdf1bba3 100644 --- a/llvm/test/Transforms/SLPVectorizer/AMDGPU/add_sub_sat-inseltpoison.ll +++ b/llvm/test/Transforms/SLPVectorizer/AMDGPU/add_sub_sat-inseltpoison.ll @@ -1,7 +1,7 @@ ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py ; RUN: opt -S -mtriple=amdgcn-amd-amdhsa -mcpu=hawaii -passes=slp-vectorizer,instcombine %s | FileCheck -check-prefixes=GCN,GFX7 %s ; RUN: opt -S -mtriple=amdgcn-amd-amdhsa -mcpu=fiji -passes=slp-vectorizer,instcombine %s | FileCheck -check-prefixes=GCN,GFX8 %s -; RUN: opt -S -mtriple=amdgcn-amd-amdhsa -mcpu=gfx900 -passes=slp-vectorizer,instcombine %s | FileCheck -check-prefixes=GCN,GFX8 %s +; RUN: opt -S -mtriple=amdgcn-amd-amdhsa -mcpu=gfx900 -passes=slp-vectorizer,instcombine %s | FileCheck -check-prefixes=GCN,GFX9 %s define <2 x i16> @uadd_sat_v2i16(<2 x i16> %arg0, <2 x i16> %arg1) { ; GFX7-LABEL: @uadd_sat_v2i16( @@ -21,6 +21,11 @@ define <2 x i16> @uadd_sat_v2i16(<2 x i16> %arg0, <2 x i16> %arg1) { ; GFX8-NEXT: [[TMP0:%.*]] = call <2 x i16> @llvm.uadd.sat.v2i16(<2 x i16> [[ARG0:%.*]], <2 x i16> [[ARG1:%.*]]) ; GFX8-NEXT: ret <2 x i16> [[TMP0]] ; +; GFX9-LABEL: @uadd_sat_v2i16( +; GFX9-NEXT: bb: +; GFX9-NEXT: [[TMP0:%.*]] = call <2 x i16> @llvm.uadd.sat.v2i16(<2 x i16> [[ARG0:%.*]], <2 x i16> [[ARG1:%.*]]) +; GFX9-NEXT: ret <2 x i16> [[TMP0]] +; bb: %arg0.0 = extractelement <2 x i16> %arg0, i64 0 %arg0.1 = extractelement <2 x i16> %arg0, i64 1 @@ -51,6 +56,11 @@ define <2 x i16> @usub_sat_v2i16(<2 x i16> %arg0, <2 x i16> %arg1) { ; GFX8-NEXT: [[TMP0:%.*]] = call <2 x i16> @llvm.usub.sat.v2i16(<2 x i16> [[ARG0:%.*]], <2 x i16> [[ARG1:%.*]]) ; GFX8-NEXT: ret <2 x i16> [[TMP0]] ; +; GFX9-LABEL: @usub_sat_v2i16( +; GFX9-NEXT: bb: +; GFX9-NEXT: [[TMP0:%.*]] = call <2 x i16> @llvm.usub.sat.v2i16(<2 x i16> [[ARG0:%.*]], <2 x i16> [[ARG1:%.*]]) +; GFX9-NEXT: ret <2 x i16> [[TMP0]] +; bb: %arg0.0 = extractelement <2 x i16> %arg0, i64 0 %arg0.1 = extractelement <2 x i16> %arg0, i64 1 @@ -81,6 +91,11 @@ define <2 x i16> @sadd_sat_v2i16(<2 x i16> %arg0, <2 x i16> %arg1) { ; GFX8-NEXT: [[TMP0:%.*]] = call <2 x i16> @llvm.sadd.sat.v2i16(<2 x i16> [[ARG0:%.*]], <2 x i16> [[ARG1:%.*]]) ; GFX8-NEXT: ret <2 x i16> [[TMP0]] ; +; GFX9-LABEL: @sadd_sat_v2i16( +; GFX9-NEXT: bb: +; GFX9-NEXT: [[TMP0:%.*]] = call <2 x i16> @llvm.sadd.sat.v2i16(<2 x i16> [[ARG0:%.*]], <2 x i16> [[ARG1:%.*]]) +; GFX9-NEXT: ret <2 x i16> [[TMP0]] +; bb: %arg0.0 = extractelement <2 x i16> %arg0, i64 0 %arg0.1 = extractelement <2 x i16> %arg0, i64 1 @@ -111,6 +126,11 @@ define <2 x i16> @ssub_sat_v2i16(<2 x i16> %arg0, <2 x i16> %arg1) { ; GFX8-NEXT: [[TMP0:%.*]] = call <2 x i16> @llvm.ssub.sat.v2i16(<2 x i16> [[ARG0:%.*]], <2 x i16> [[ARG1:%.*]]) ; GFX8-NEXT: ret <2 x i16> [[TMP0]] ; +; GFX9-LABEL: @ssub_sat_v2i16( +; GFX9-NEXT: bb: +; GFX9-NEXT: [[TMP0:%.*]] = call <2 x i16> @llvm.ssub.sat.v2i16(<2 x i16> [[ARG0:%.*]], <2 x i16> [[ARG1:%.*]]) +; GFX9-NEXT: ret <2 x i16> [[TMP0]] +; bb: %arg0.0 = extractelement <2 x i16> %arg0, i64 0 %arg0.1 = extractelement <2 x i16> %arg0, i64 1 @@ -252,6 +272,18 @@ define <3 x i16> @uadd_sat_v3i16(<3 x i16> %arg0, <3 x i16> %arg1) { ; GFX8-NEXT: [[INS_2:%.*]] = insertelement <3 x i16> [[TMP3]], i16 [[ADD_2]], i64 2 ; GFX8-NEXT: ret <3 x i16> [[INS_2]] ; +; GFX9-LABEL: @uadd_sat_v3i16( +; GFX9-NEXT: bb: +; GFX9-NEXT: [[ARG0_2:%.*]] = extractelement <3 x i16> [[ARG0:%.*]], i64 2 +; GFX9-NEXT: [[ARG1_2:%.*]] = extractelement <3 x i16> [[ARG1:%.*]], i64 2 +; GFX9-NEXT: [[TMP0:%.*]] = shufflevector <3 x i16> [[ARG0]], <3 x i16> poison, <2 x i32> +; GFX9-NEXT: [[TMP1:%.*]] = shufflevector <3 x i16> [[ARG1]], <3 x i16> poison, <2 x i32> +; GFX9-NEXT: [[TMP2:%.*]] = call <2 x i16> @llvm.uadd.sat.v2i16(<2 x i16> [[TMP0]], <2 x i16> [[TMP1]]) +; GFX9-NEXT: [[ADD_2:%.*]] = call i16 @llvm.uadd.sat.i16(i16 [[ARG0_2]], i16 [[ARG1_2]]) +; GFX9-NEXT: [[TMP3:%.*]] = shufflevector <2 x i16> [[TMP2]], <2 x i16> poison, <3 x i32> +; GFX9-NEXT: [[INS_2:%.*]] = insertelement <3 x i16> [[TMP3]], i16 [[ADD_2]], i64 2 +; GFX9-NEXT: ret <3 x i16> [[INS_2]] +; bb: %arg0.0 = extractelement <3 x i16> %arg0, i64 0 %arg0.1 = extractelement <3 x i16> %arg0, i64 1 @@ -291,19 +323,25 @@ define <4 x i16> @uadd_sat_v4i16(<4 x i16> %arg0, <4 x i16> %arg1) { ; ; GFX8-LABEL: @uadd_sat_v4i16( ; GFX8-NEXT: bb: -; GFX8-NEXT: [[ARG0_2:%.*]] = extractelement <4 x i16> [[ARG0:%.*]], i64 2 -; GFX8-NEXT: [[ARG0_3:%.*]] = extractelement <4 x i16> [[ARG0]], i64 3 -; GFX8-NEXT: [[ARG1_2:%.*]] = extractelement <4 x i16> [[ARG1:%.*]], i64 2 -; GFX8-NEXT: [[ARG1_3:%.*]] = extractelement <4 x i16> [[ARG1]], i64 3 -; GFX8-NEXT: [[TMP0:%.*]] = shufflevector <4 x i16> [[ARG0]], <4 x i16> poison, <2 x i32> -; GFX8-NEXT: [[TMP1:%.*]] = shufflevector <4 x i16> [[ARG1]], <4 x i16> poison, <2 x i32> +; GFX8-NEXT: [[TMP0:%.*]] = shufflevector <4 x i16> [[ARG0:%.*]], <4 x i16> poison, <2 x i32> +; GFX8-NEXT: [[TMP1:%.*]] = shufflevector <4 x i16> [[ARG1:%.*]], <4 x i16> poison, <2 x i32> ; GFX8-NEXT: [[TMP2:%.*]] = call <2 x i16> @llvm.uadd.sat.v2i16(<2 x i16> [[TMP0]], <2 x i16> [[TMP1]]) -; GFX8-NEXT: [[ADD_2:%.*]] = call i16 @llvm.uadd.sat.i16(i16 [[ARG0_2]], i16 [[ARG1_2]]) -; GFX8-NEXT: [[ADD_3:%.*]] = call i16 @llvm.uadd.sat.i16(i16 [[ARG0_3]], i16 [[ARG1_3]]) -; GFX8-NEXT: [[TMP3:%.*]] = shufflevector <2 x i16> [[TMP2]], <2 x i16> poison, <4 x i32> -; GFX8-NEXT: [[INS_2:%.*]] = insertelement <4 x i16> [[TMP3]], i16 [[ADD_2]], i64 2 -; GFX8-NEXT: [[INS_3:%.*]] = insertelement <4 x i16> [[INS_2]], i16 [[ADD_3]], i64 3 -; GFX8-NEXT: ret <4 x i16> [[INS_3]] +; GFX8-NEXT: [[TMP3:%.*]] = shufflevector <4 x i16> [[ARG0]], <4 x i16> poison, <2 x i32> +; GFX8-NEXT: [[TMP4:%.*]] = shufflevector <4 x i16> [[ARG1]], <4 x i16> poison, <2 x i32> +; GFX8-NEXT: [[TMP5:%.*]] = call <2 x i16> @llvm.uadd.sat.v2i16(<2 x i16> [[TMP3]], <2 x i16> [[TMP4]]) +; GFX8-NEXT: [[INS_31:%.*]] = shufflevector <2 x i16> [[TMP2]], <2 x i16> [[TMP5]], <4 x i32> +; GFX8-NEXT: ret <4 x i16> [[INS_31]] +; +; GFX9-LABEL: @uadd_sat_v4i16( +; GFX9-NEXT: bb: +; GFX9-NEXT: [[TMP0:%.*]] = shufflevector <4 x i16> [[ARG0:%.*]], <4 x i16> poison, <2 x i32> +; GFX9-NEXT: [[TMP1:%.*]] = shufflevector <4 x i16> [[ARG1:%.*]], <4 x i16> poison, <2 x i32> +; GFX9-NEXT: [[TMP2:%.*]] = call <2 x i16> @llvm.uadd.sat.v2i16(<2 x i16> [[TMP0]], <2 x i16> [[TMP1]]) +; GFX9-NEXT: [[TMP3:%.*]] = shufflevector <4 x i16> [[ARG0]], <4 x i16> poison, <2 x i32> +; GFX9-NEXT: [[TMP4:%.*]] = shufflevector <4 x i16> [[ARG1]], <4 x i16> poison, <2 x i32> +; GFX9-NEXT: [[TMP5:%.*]] = call <2 x i16> @llvm.uadd.sat.v2i16(<2 x i16> [[TMP3]], <2 x i16> [[TMP4]]) +; GFX9-NEXT: [[INS_31:%.*]] = shufflevector <2 x i16> [[TMP2]], <2 x i16> [[TMP5]], <4 x i32> +; GFX9-NEXT: ret <4 x i16> [[INS_31]] ; bb: %arg0.0 = extractelement <4 x i16> %arg0, i64 0 diff --git a/llvm/test/Transforms/SLPVectorizer/AMDGPU/add_sub_sat.ll b/llvm/test/Transforms/SLPVectorizer/AMDGPU/add_sub_sat.ll index 2038400a0586..0bb641371825 100644 --- a/llvm/test/Transforms/SLPVectorizer/AMDGPU/add_sub_sat.ll +++ b/llvm/test/Transforms/SLPVectorizer/AMDGPU/add_sub_sat.ll @@ -1,7 +1,7 @@ ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py ; RUN: opt -S -mtriple=amdgcn-amd-amdhsa -mcpu=hawaii -passes=slp-vectorizer,instcombine %s | FileCheck -check-prefixes=GCN,GFX7 %s ; RUN: opt -S -mtriple=amdgcn-amd-amdhsa -mcpu=fiji -passes=slp-vectorizer,instcombine %s | FileCheck -check-prefixes=GCN,GFX8 %s -; RUN: opt -S -mtriple=amdgcn-amd-amdhsa -mcpu=gfx900 -passes=slp-vectorizer,instcombine %s | FileCheck -check-prefixes=GCN,GFX8 %s +; RUN: opt -S -mtriple=amdgcn-amd-amdhsa -mcpu=gfx900 -passes=slp-vectorizer,instcombine %s | FileCheck -check-prefixes=GCN,GFX9 %s define <2 x i16> @uadd_sat_v2i16(<2 x i16> %arg0, <2 x i16> %arg1) { ; GFX7-LABEL: @uadd_sat_v2i16( @@ -21,6 +21,11 @@ define <2 x i16> @uadd_sat_v2i16(<2 x i16> %arg0, <2 x i16> %arg1) { ; GFX8-NEXT: [[TMP0:%.*]] = call <2 x i16> @llvm.uadd.sat.v2i16(<2 x i16> [[ARG0:%.*]], <2 x i16> [[ARG1:%.*]]) ; GFX8-NEXT: ret <2 x i16> [[TMP0]] ; +; GFX9-LABEL: @uadd_sat_v2i16( +; GFX9-NEXT: bb: +; GFX9-NEXT: [[TMP0:%.*]] = call <2 x i16> @llvm.uadd.sat.v2i16(<2 x i16> [[ARG0:%.*]], <2 x i16> [[ARG1:%.*]]) +; GFX9-NEXT: ret <2 x i16> [[TMP0]] +; bb: %arg0.0 = extractelement <2 x i16> %arg0, i64 0 %arg0.1 = extractelement <2 x i16> %arg0, i64 1 @@ -51,6 +56,11 @@ define <2 x i16> @usub_sat_v2i16(<2 x i16> %arg0, <2 x i16> %arg1) { ; GFX8-NEXT: [[TMP0:%.*]] = call <2 x i16> @llvm.usub.sat.v2i16(<2 x i16> [[ARG0:%.*]], <2 x i16> [[ARG1:%.*]]) ; GFX8-NEXT: ret <2 x i16> [[TMP0]] ; +; GFX9-LABEL: @usub_sat_v2i16( +; GFX9-NEXT: bb: +; GFX9-NEXT: [[TMP0:%.*]] = call <2 x i16> @llvm.usub.sat.v2i16(<2 x i16> [[ARG0:%.*]], <2 x i16> [[ARG1:%.*]]) +; GFX9-NEXT: ret <2 x i16> [[TMP0]] +; bb: %arg0.0 = extractelement <2 x i16> %arg0, i64 0 %arg0.1 = extractelement <2 x i16> %arg0, i64 1 @@ -81,6 +91,11 @@ define <2 x i16> @sadd_sat_v2i16(<2 x i16> %arg0, <2 x i16> %arg1) { ; GFX8-NEXT: [[TMP0:%.*]] = call <2 x i16> @llvm.sadd.sat.v2i16(<2 x i16> [[ARG0:%.*]], <2 x i16> [[ARG1:%.*]]) ; GFX8-NEXT: ret <2 x i16> [[TMP0]] ; +; GFX9-LABEL: @sadd_sat_v2i16( +; GFX9-NEXT: bb: +; GFX9-NEXT: [[TMP0:%.*]] = call <2 x i16> @llvm.sadd.sat.v2i16(<2 x i16> [[ARG0:%.*]], <2 x i16> [[ARG1:%.*]]) +; GFX9-NEXT: ret <2 x i16> [[TMP0]] +; bb: %arg0.0 = extractelement <2 x i16> %arg0, i64 0 %arg0.1 = extractelement <2 x i16> %arg0, i64 1 @@ -111,6 +126,11 @@ define <2 x i16> @ssub_sat_v2i16(<2 x i16> %arg0, <2 x i16> %arg1) { ; GFX8-NEXT: [[TMP0:%.*]] = call <2 x i16> @llvm.ssub.sat.v2i16(<2 x i16> [[ARG0:%.*]], <2 x i16> [[ARG1:%.*]]) ; GFX8-NEXT: ret <2 x i16> [[TMP0]] ; +; GFX9-LABEL: @ssub_sat_v2i16( +; GFX9-NEXT: bb: +; GFX9-NEXT: [[TMP0:%.*]] = call <2 x i16> @llvm.ssub.sat.v2i16(<2 x i16> [[ARG0:%.*]], <2 x i16> [[ARG1:%.*]]) +; GFX9-NEXT: ret <2 x i16> [[TMP0]] +; bb: %arg0.0 = extractelement <2 x i16> %arg0, i64 0 %arg0.1 = extractelement <2 x i16> %arg0, i64 1 @@ -252,6 +272,18 @@ define <3 x i16> @uadd_sat_v3i16(<3 x i16> %arg0, <3 x i16> %arg1) { ; GFX8-NEXT: [[INS_2:%.*]] = insertelement <3 x i16> [[TMP3]], i16 [[ADD_2]], i64 2 ; GFX8-NEXT: ret <3 x i16> [[INS_2]] ; +; GFX9-LABEL: @uadd_sat_v3i16( +; GFX9-NEXT: bb: +; GFX9-NEXT: [[ARG0_2:%.*]] = extractelement <3 x i16> [[ARG0:%.*]], i64 2 +; GFX9-NEXT: [[ARG1_2:%.*]] = extractelement <3 x i16> [[ARG1:%.*]], i64 2 +; GFX9-NEXT: [[TMP0:%.*]] = shufflevector <3 x i16> [[ARG0]], <3 x i16> poison, <2 x i32> +; GFX9-NEXT: [[TMP1:%.*]] = shufflevector <3 x i16> [[ARG1]], <3 x i16> poison, <2 x i32> +; GFX9-NEXT: [[TMP2:%.*]] = call <2 x i16> @llvm.uadd.sat.v2i16(<2 x i16> [[TMP0]], <2 x i16> [[TMP1]]) +; GFX9-NEXT: [[ADD_2:%.*]] = call i16 @llvm.uadd.sat.i16(i16 [[ARG0_2]], i16 [[ARG1_2]]) +; GFX9-NEXT: [[TMP3:%.*]] = shufflevector <2 x i16> [[TMP2]], <2 x i16> poison, <3 x i32> +; GFX9-NEXT: [[INS_2:%.*]] = insertelement <3 x i16> [[TMP3]], i16 [[ADD_2]], i64 2 +; GFX9-NEXT: ret <3 x i16> [[INS_2]] +; bb: %arg0.0 = extractelement <3 x i16> %arg0, i64 0 %arg0.1 = extractelement <3 x i16> %arg0, i64 1 @@ -291,19 +323,25 @@ define <4 x i16> @uadd_sat_v4i16(<4 x i16> %arg0, <4 x i16> %arg1) { ; ; GFX8-LABEL: @uadd_sat_v4i16( ; GFX8-NEXT: bb: -; GFX8-NEXT: [[ARG0_2:%.*]] = extractelement <4 x i16> [[ARG0:%.*]], i64 2 -; GFX8-NEXT: [[ARG0_3:%.*]] = extractelement <4 x i16> [[ARG0]], i64 3 -; GFX8-NEXT: [[ARG1_2:%.*]] = extractelement <4 x i16> [[ARG1:%.*]], i64 2 -; GFX8-NEXT: [[ARG1_3:%.*]] = extractelement <4 x i16> [[ARG1]], i64 3 -; GFX8-NEXT: [[TMP0:%.*]] = shufflevector <4 x i16> [[ARG0]], <4 x i16> poison, <2 x i32> -; GFX8-NEXT: [[TMP1:%.*]] = shufflevector <4 x i16> [[ARG1]], <4 x i16> poison, <2 x i32> +; GFX8-NEXT: [[TMP0:%.*]] = shufflevector <4 x i16> [[ARG0:%.*]], <4 x i16> poison, <2 x i32> +; GFX8-NEXT: [[TMP1:%.*]] = shufflevector <4 x i16> [[ARG1:%.*]], <4 x i16> poison, <2 x i32> ; GFX8-NEXT: [[TMP2:%.*]] = call <2 x i16> @llvm.uadd.sat.v2i16(<2 x i16> [[TMP0]], <2 x i16> [[TMP1]]) -; GFX8-NEXT: [[ADD_2:%.*]] = call i16 @llvm.uadd.sat.i16(i16 [[ARG0_2]], i16 [[ARG1_2]]) -; GFX8-NEXT: [[ADD_3:%.*]] = call i16 @llvm.uadd.sat.i16(i16 [[ARG0_3]], i16 [[ARG1_3]]) -; GFX8-NEXT: [[TMP3:%.*]] = shufflevector <2 x i16> [[TMP2]], <2 x i16> poison, <4 x i32> -; GFX8-NEXT: [[INS_2:%.*]] = insertelement <4 x i16> [[TMP3]], i16 [[ADD_2]], i64 2 -; GFX8-NEXT: [[INS_3:%.*]] = insertelement <4 x i16> [[INS_2]], i16 [[ADD_3]], i64 3 -; GFX8-NEXT: ret <4 x i16> [[INS_3]] +; GFX8-NEXT: [[TMP3:%.*]] = shufflevector <4 x i16> [[ARG0]], <4 x i16> poison, <2 x i32> +; GFX8-NEXT: [[TMP4:%.*]] = shufflevector <4 x i16> [[ARG1]], <4 x i16> poison, <2 x i32> +; GFX8-NEXT: [[TMP5:%.*]] = call <2 x i16> @llvm.uadd.sat.v2i16(<2 x i16> [[TMP3]], <2 x i16> [[TMP4]]) +; GFX8-NEXT: [[INS_31:%.*]] = shufflevector <2 x i16> [[TMP2]], <2 x i16> [[TMP5]], <4 x i32> +; GFX8-NEXT: ret <4 x i16> [[INS_31]] +; +; GFX9-LABEL: @uadd_sat_v4i16( +; GFX9-NEXT: bb: +; GFX9-NEXT: [[TMP0:%.*]] = shufflevector <4 x i16> [[ARG0:%.*]], <4 x i16> poison, <2 x i32> +; GFX9-NEXT: [[TMP1:%.*]] = shufflevector <4 x i16> [[ARG1:%.*]], <4 x i16> poison, <2 x i32> +; GFX9-NEXT: [[TMP2:%.*]] = call <2 x i16> @llvm.uadd.sat.v2i16(<2 x i16> [[TMP0]], <2 x i16> [[TMP1]]) +; GFX9-NEXT: [[TMP3:%.*]] = shufflevector <4 x i16> [[ARG0]], <4 x i16> poison, <2 x i32> +; GFX9-NEXT: [[TMP4:%.*]] = shufflevector <4 x i16> [[ARG1]], <4 x i16> poison, <2 x i32> +; GFX9-NEXT: [[TMP5:%.*]] = call <2 x i16> @llvm.uadd.sat.v2i16(<2 x i16> [[TMP3]], <2 x i16> [[TMP4]]) +; GFX9-NEXT: [[INS_31:%.*]] = shufflevector <2 x i16> [[TMP2]], <2 x i16> [[TMP5]], <4 x i32> +; GFX9-NEXT: ret <4 x i16> [[INS_31]] ; bb: %arg0.0 = extractelement <4 x i16> %arg0, i64 0 diff --git a/llvm/test/Transforms/SLPVectorizer/AMDGPU/crash_extract_subvector_cost.ll b/llvm/test/Transforms/SLPVectorizer/AMDGPU/crash_extract_subvector_cost.ll index 0a020c855cc2..e474bab2ad96 100644 --- a/llvm/test/Transforms/SLPVectorizer/AMDGPU/crash_extract_subvector_cost.ll +++ b/llvm/test/Transforms/SLPVectorizer/AMDGPU/crash_extract_subvector_cost.ll @@ -4,15 +4,10 @@ define <2 x i16> @uadd_sat_v9i16_combine_vi16(<9 x i16> %arg0, <9 x i16> %arg1) { ; CHECK-LABEL: @uadd_sat_v9i16_combine_vi16( ; CHECK-NEXT: bb: -; CHECK-NEXT: [[ARG0_1:%.*]] = extractelement <9 x i16> undef, i64 7 -; CHECK-NEXT: [[ARG0_2:%.*]] = extractelement <9 x i16> [[ARG0:%.*]], i64 8 -; CHECK-NEXT: [[ARG1_1:%.*]] = extractelement <9 x i16> [[ARG1:%.*]], i64 7 -; CHECK-NEXT: [[ARG1_2:%.*]] = extractelement <9 x i16> [[ARG1]], i64 8 -; CHECK-NEXT: [[ADD_1:%.*]] = call i16 @llvm.uadd.sat.i16(i16 [[ARG0_1]], i16 [[ARG1_1]]) -; CHECK-NEXT: [[ADD_2:%.*]] = call i16 @llvm.uadd.sat.i16(i16 [[ARG0_2]], i16 [[ARG1_2]]) -; CHECK-NEXT: [[INS_1:%.*]] = insertelement <2 x i16> undef, i16 [[ADD_1]], i64 0 -; CHECK-NEXT: [[INS_2:%.*]] = insertelement <2 x i16> [[INS_1]], i16 [[ADD_2]], i64 1 -; CHECK-NEXT: ret <2 x i16> [[INS_2]] +; CHECK-NEXT: [[TMP0:%.*]] = shufflevector <9 x i16> [[ARG0:%.*]], <9 x i16> poison, <2 x i32> +; CHECK-NEXT: [[TMP1:%.*]] = shufflevector <9 x i16> [[ARG1:%.*]], <9 x i16> poison, <2 x i32> +; CHECK-NEXT: [[TMP2:%.*]] = call <2 x i16> @llvm.uadd.sat.v2i16(<2 x i16> [[TMP0]], <2 x i16> [[TMP1]]) +; CHECK-NEXT: ret <2 x i16> [[TMP2]] ; bb: %arg0.1 = extractelement <9 x i16> undef, i64 7 diff --git a/llvm/test/Transforms/SLPVectorizer/AMDGPU/phi-result-use-order.ll b/llvm/test/Transforms/SLPVectorizer/AMDGPU/phi-result-use-order.ll index 46980b33e401..3b63c1e35610 100644 --- a/llvm/test/Transforms/SLPVectorizer/AMDGPU/phi-result-use-order.ll +++ b/llvm/test/Transforms/SLPVectorizer/AMDGPU/phi-result-use-order.ll @@ -4,23 +4,20 @@ define <4 x half> @phis(i1 %cmp1, <4 x half> %in1, <4 x half> %in2) { ; CHECK-LABEL: @phis( ; CHECK-NEXT: entry: -; CHECK-NEXT: [[A2:%.*]] = extractelement <4 x half> [[IN1:%.*]], i64 2 -; CHECK-NEXT: [[A3:%.*]] = extractelement <4 x half> [[IN1]], i64 3 -; CHECK-NEXT: [[TMP0:%.*]] = shufflevector <4 x half> [[IN1]], <4 x half> poison, <2 x i32> +; CHECK-NEXT: [[TMP0:%.*]] = shufflevector <4 x half> [[IN1:%.*]], <4 x half> poison, <2 x i32> +; CHECK-NEXT: [[TMP1:%.*]] = shufflevector <4 x half> [[IN1]], <4 x half> poison, <2 x i32> ; CHECK-NEXT: br i1 [[CMP1:%.*]], label [[BB1:%.*]], label [[BB0:%.*]] ; CHECK: bb0: -; CHECK-NEXT: [[B2:%.*]] = extractelement <4 x half> [[IN2:%.*]], i64 2 -; CHECK-NEXT: [[B3:%.*]] = extractelement <4 x half> [[IN2]], i64 3 -; CHECK-NEXT: [[TMP1:%.*]] = shufflevector <4 x half> [[IN2]], <4 x half> poison, <2 x i32> +; CHECK-NEXT: [[TMP2:%.*]] = shufflevector <4 x half> [[IN2:%.*]], <4 x half> poison, <2 x i32> +; CHECK-NEXT: [[TMP3:%.*]] = shufflevector <4 x half> [[IN2]], <4 x half> poison, <2 x i32> ; CHECK-NEXT: br label [[BB1]] ; CHECK: bb1: -; CHECK-NEXT: [[C2:%.*]] = phi half [ [[A2]], [[ENTRY:%.*]] ], [ [[B2]], [[BB0]] ] -; CHECK-NEXT: [[C3:%.*]] = phi half [ [[A3]], [[ENTRY]] ], [ [[B3]], [[BB0]] ] -; CHECK-NEXT: [[TMP2:%.*]] = phi <2 x half> [ [[TMP0]], [[ENTRY]] ], [ [[TMP1]], [[BB0]] ] -; CHECK-NEXT: [[TMP3:%.*]] = shufflevector <2 x half> [[TMP2]], <2 x half> poison, <4 x i32> -; CHECK-NEXT: [[O2:%.*]] = insertelement <4 x half> [[TMP3]], half [[C2]], i64 2 -; CHECK-NEXT: [[O3:%.*]] = insertelement <4 x half> [[O2]], half [[C3]], i64 3 -; CHECK-NEXT: ret <4 x half> [[O3]] +; CHECK-NEXT: [[TMP4:%.*]] = phi <2 x half> [ [[TMP0]], [[ENTRY:%.*]] ], [ [[TMP2]], [[BB0]] ] +; CHECK-NEXT: [[TMP5:%.*]] = phi <2 x half> [ [[TMP1]], [[ENTRY]] ], [ [[TMP3]], [[BB0]] ] +; CHECK-NEXT: [[TMP6:%.*]] = shufflevector <2 x half> [[TMP4]], <2 x half> poison, <4 x i32> +; CHECK-NEXT: [[TMP7:%.*]] = shufflevector <2 x half> [[TMP5]], <2 x half> poison, <4 x i32> +; CHECK-NEXT: [[TMP8:%.*]] = shufflevector <2 x half> [[TMP4]], <2 x half> [[TMP5]], <4 x i32> +; CHECK-NEXT: ret <4 x half> [[TMP8]] ; entry: %a0 = extractelement <4 x half> %in1, i64 0 @@ -52,23 +49,20 @@ bb1: define <4 x half> @phis_reverse(i1 %cmp1, <4 x half> %in1, <4 x half> %in2) { ; CHECK-LABEL: @phis_reverse( ; CHECK-NEXT: entry: -; CHECK-NEXT: [[A2:%.*]] = extractelement <4 x half> [[IN1:%.*]], i64 2 -; CHECK-NEXT: [[A3:%.*]] = extractelement <4 x half> [[IN1]], i64 3 -; CHECK-NEXT: [[TMP0:%.*]] = shufflevector <4 x half> [[IN1]], <4 x half> poison, <2 x i32> +; CHECK-NEXT: [[TMP0:%.*]] = shufflevector <4 x half> [[IN1:%.*]], <4 x half> poison, <2 x i32> +; CHECK-NEXT: [[TMP1:%.*]] = shufflevector <4 x half> [[IN1]], <4 x half> poison, <2 x i32> ; CHECK-NEXT: br i1 [[CMP1:%.*]], label [[BB1:%.*]], label [[BB0:%.*]] ; CHECK: bb0: -; CHECK-NEXT: [[B2:%.*]] = extractelement <4 x half> [[IN2:%.*]], i64 2 -; CHECK-NEXT: [[B3:%.*]] = extractelement <4 x half> [[IN2]], i64 3 -; CHECK-NEXT: [[TMP1:%.*]] = shufflevector <4 x half> [[IN2]], <4 x half> poison, <2 x i32> +; CHECK-NEXT: [[TMP2:%.*]] = shufflevector <4 x half> [[IN2:%.*]], <4 x half> poison, <2 x i32> +; CHECK-NEXT: [[TMP3:%.*]] = shufflevector <4 x half> [[IN2]], <4 x half> poison, <2 x i32> ; CHECK-NEXT: br label [[BB1]] ; CHECK: bb1: -; CHECK-NEXT: [[C3:%.*]] = phi half [ [[A3]], [[ENTRY:%.*]] ], [ [[B3]], [[BB0]] ] -; CHECK-NEXT: [[C2:%.*]] = phi half [ [[A2]], [[ENTRY]] ], [ [[B2]], [[BB0]] ] -; CHECK-NEXT: [[TMP2:%.*]] = phi <2 x half> [ [[TMP0]], [[ENTRY]] ], [ [[TMP1]], [[BB0]] ] -; CHECK-NEXT: [[TMP3:%.*]] = shufflevector <2 x half> [[TMP2]], <2 x half> poison, <4 x i32> -; CHECK-NEXT: [[O2:%.*]] = insertelement <4 x half> [[TMP3]], half [[C2]], i64 2 -; CHECK-NEXT: [[O3:%.*]] = insertelement <4 x half> [[O2]], half [[C3]], i64 3 -; CHECK-NEXT: ret <4 x half> [[O3]] +; CHECK-NEXT: [[TMP4:%.*]] = phi <2 x half> [ [[TMP0]], [[ENTRY:%.*]] ], [ [[TMP2]], [[BB0]] ] +; CHECK-NEXT: [[TMP5:%.*]] = phi <2 x half> [ [[TMP1]], [[ENTRY]] ], [ [[TMP3]], [[BB0]] ] +; CHECK-NEXT: [[TMP6:%.*]] = shufflevector <2 x half> [[TMP5]], <2 x half> poison, <4 x i32> +; CHECK-NEXT: [[TMP7:%.*]] = shufflevector <2 x half> [[TMP4]], <2 x half> poison, <4 x i32> +; CHECK-NEXT: [[TMP8:%.*]] = shufflevector <4 x half> [[TMP6]], <4 x half> [[TMP7]], <4 x i32> +; CHECK-NEXT: ret <4 x half> [[TMP8]] ; entry: %a0 = extractelement <4 x half> %in1, i64 0 diff --git a/llvm/test/Transforms/SLPVectorizer/AMDGPU/reduction.ll b/llvm/test/Transforms/SLPVectorizer/AMDGPU/reduction.ll index b34b9a352536..dfa8be974177 100644 --- a/llvm/test/Transforms/SLPVectorizer/AMDGPU/reduction.ll +++ b/llvm/test/Transforms/SLPVectorizer/AMDGPU/reduction.ll @@ -3,21 +3,10 @@ ; RUN: opt -S -mtriple=amdgcn-amd-amdhsa -mcpu=fiji -passes=slp-vectorizer,dce < %s | FileCheck -check-prefixes=GCN,VI %s define half @reduction_half4(<4 x half> %a) { -; GFX9-LABEL: @reduction_half4( -; GFX9-NEXT: entry: -; GFX9-NEXT: [[TMP0:%.*]] = call fast half @llvm.vector.reduce.fadd.v4f16(half 0xH8000, <4 x half> [[A:%.*]]) -; GFX9-NEXT: ret half [[TMP0]] -; -; VI-LABEL: @reduction_half4( -; VI-NEXT: entry: -; VI-NEXT: [[ELT0:%.*]] = extractelement <4 x half> [[A:%.*]], i64 0 -; VI-NEXT: [[ELT1:%.*]] = extractelement <4 x half> [[A]], i64 1 -; VI-NEXT: [[ELT2:%.*]] = extractelement <4 x half> [[A]], i64 2 -; VI-NEXT: [[ELT3:%.*]] = extractelement <4 x half> [[A]], i64 3 -; VI-NEXT: [[ADD1:%.*]] = fadd fast half [[ELT1]], [[ELT0]] -; VI-NEXT: [[ADD2:%.*]] = fadd fast half [[ELT2]], [[ADD1]] -; VI-NEXT: [[ADD3:%.*]] = fadd fast half [[ELT3]], [[ADD2]] -; VI-NEXT: ret half [[ADD3]] +; GCN-LABEL: @reduction_half4( +; GCN-NEXT: entry: +; GCN-NEXT: [[TMP0:%.*]] = call fast half @llvm.vector.reduce.fadd.v4f16(half 0xH8000, <4 x half> [[A:%.*]]) +; GCN-NEXT: ret half [[TMP0]] ; entry: %elt0 = extractelement <4 x half> %a, i64 0 @@ -33,29 +22,10 @@ entry: } define half @reduction_half8(<8 x half> %vec8) { -; GFX9-LABEL: @reduction_half8( -; GFX9-NEXT: entry: -; GFX9-NEXT: [[TMP0:%.*]] = call fast half @llvm.vector.reduce.fadd.v8f16(half 0xH8000, <8 x half> [[VEC8:%.*]]) -; GFX9-NEXT: ret half [[TMP0]] -; -; VI-LABEL: @reduction_half8( -; VI-NEXT: entry: -; VI-NEXT: [[ELT0:%.*]] = extractelement <8 x half> [[VEC8:%.*]], i64 0 -; VI-NEXT: [[ELT1:%.*]] = extractelement <8 x half> [[VEC8]], i64 1 -; VI-NEXT: [[ELT2:%.*]] = extractelement <8 x half> [[VEC8]], i64 2 -; VI-NEXT: [[ELT3:%.*]] = extractelement <8 x half> [[VEC8]], i64 3 -; VI-NEXT: [[ELT4:%.*]] = extractelement <8 x half> [[VEC8]], i64 4 -; VI-NEXT: [[ELT5:%.*]] = extractelement <8 x half> [[VEC8]], i64 5 -; VI-NEXT: [[ELT6:%.*]] = extractelement <8 x half> [[VEC8]], i64 6 -; VI-NEXT: [[ELT7:%.*]] = extractelement <8 x half> [[VEC8]], i64 7 -; VI-NEXT: [[ADD1:%.*]] = fadd fast half [[ELT1]], [[ELT0]] -; VI-NEXT: [[ADD2:%.*]] = fadd fast half [[ELT2]], [[ADD1]] -; VI-NEXT: [[ADD3:%.*]] = fadd fast half [[ELT3]], [[ADD2]] -; VI-NEXT: [[ADD4:%.*]] = fadd fast half [[ELT4]], [[ADD3]] -; VI-NEXT: [[ADD5:%.*]] = fadd fast half [[ELT5]], [[ADD4]] -; VI-NEXT: [[ADD6:%.*]] = fadd fast half [[ELT6]], [[ADD5]] -; VI-NEXT: [[ADD7:%.*]] = fadd fast half [[ELT7]], [[ADD6]] -; VI-NEXT: ret half [[ADD7]] +; GCN-LABEL: @reduction_half8( +; GCN-NEXT: entry: +; GCN-NEXT: [[TMP0:%.*]] = call fast half @llvm.vector.reduce.fadd.v8f16(half 0xH8000, <8 x half> [[VEC8:%.*]]) +; GCN-NEXT: ret half [[TMP0]] ; entry: %elt0 = extractelement <8 x half> %vec8, i64 0 @@ -86,15 +56,7 @@ define half @reduction_half16(<16 x half> %vec16) { ; ; VI-LABEL: @reduction_half16( ; VI-NEXT: entry: -; VI-NEXT: [[ELT0:%.*]] = extractelement <16 x half> [[VEC16:%.*]], i64 0 -; VI-NEXT: [[ELT1:%.*]] = extractelement <16 x half> [[VEC16]], i64 1 -; VI-NEXT: [[ELT2:%.*]] = extractelement <16 x half> [[VEC16]], i64 2 -; VI-NEXT: [[ELT3:%.*]] = extractelement <16 x half> [[VEC16]], i64 3 -; VI-NEXT: [[ELT4:%.*]] = extractelement <16 x half> [[VEC16]], i64 4 -; VI-NEXT: [[ELT5:%.*]] = extractelement <16 x half> [[VEC16]], i64 5 -; VI-NEXT: [[ELT6:%.*]] = extractelement <16 x half> [[VEC16]], i64 6 -; VI-NEXT: [[ELT7:%.*]] = extractelement <16 x half> [[VEC16]], i64 7 -; VI-NEXT: [[ELT8:%.*]] = extractelement <16 x half> [[VEC16]], i64 8 +; VI-NEXT: [[ELT8:%.*]] = extractelement <16 x half> [[VEC16:%.*]], i64 8 ; VI-NEXT: [[ELT9:%.*]] = extractelement <16 x half> [[VEC16]], i64 9 ; VI-NEXT: [[ELT10:%.*]] = extractelement <16 x half> [[VEC16]], i64 10 ; VI-NEXT: [[ELT11:%.*]] = extractelement <16 x half> [[VEC16]], i64 11 @@ -102,22 +64,17 @@ define half @reduction_half16(<16 x half> %vec16) { ; VI-NEXT: [[ELT13:%.*]] = extractelement <16 x half> [[VEC16]], i64 13 ; VI-NEXT: [[ELT14:%.*]] = extractelement <16 x half> [[VEC16]], i64 14 ; VI-NEXT: [[ELT15:%.*]] = extractelement <16 x half> [[VEC16]], i64 15 -; VI-NEXT: [[ADD1:%.*]] = fadd fast half [[ELT1]], [[ELT0]] -; VI-NEXT: [[ADD2:%.*]] = fadd fast half [[ELT2]], [[ADD1]] -; VI-NEXT: [[ADD3:%.*]] = fadd fast half [[ELT3]], [[ADD2]] -; VI-NEXT: [[ADD4:%.*]] = fadd fast half [[ELT4]], [[ADD3]] -; VI-NEXT: [[ADD5:%.*]] = fadd fast half [[ELT5]], [[ADD4]] -; VI-NEXT: [[ADD6:%.*]] = fadd fast half [[ELT6]], [[ADD5]] -; VI-NEXT: [[ADD7:%.*]] = fadd fast half [[ELT7]], [[ADD6]] -; VI-NEXT: [[ADD8:%.*]] = fadd fast half [[ELT8]], [[ADD7]] -; VI-NEXT: [[ADD9:%.*]] = fadd fast half [[ELT9]], [[ADD8]] -; VI-NEXT: [[ADD10:%.*]] = fadd fast half [[ELT10]], [[ADD9]] -; VI-NEXT: [[ADD11:%.*]] = fadd fast half [[ELT11]], [[ADD10]] -; VI-NEXT: [[ADD12:%.*]] = fadd fast half [[ELT12]], [[ADD11]] -; VI-NEXT: [[ADD13:%.*]] = fadd fast half [[ELT13]], [[ADD12]] -; VI-NEXT: [[ADD14:%.*]] = fadd fast half [[ELT14]], [[ADD13]] -; VI-NEXT: [[ADD15:%.*]] = fadd fast half [[ELT15]], [[ADD14]] -; VI-NEXT: ret half [[ADD15]] +; VI-NEXT: [[TMP0:%.*]] = shufflevector <16 x half> [[VEC16]], <16 x half> poison, <8 x i32> +; VI-NEXT: [[TMP1:%.*]] = call fast half @llvm.vector.reduce.fadd.v8f16(half 0xH8000, <8 x half> [[TMP0]]) +; VI-NEXT: [[OP_RDX:%.*]] = fadd fast half [[TMP1]], [[ELT8]] +; VI-NEXT: [[OP_RDX1:%.*]] = fadd fast half [[ELT9]], [[ELT10]] +; VI-NEXT: [[OP_RDX2:%.*]] = fadd fast half [[ELT11]], [[ELT12]] +; VI-NEXT: [[OP_RDX3:%.*]] = fadd fast half [[ELT13]], [[ELT14]] +; VI-NEXT: [[OP_RDX4:%.*]] = fadd fast half [[OP_RDX]], [[OP_RDX1]] +; VI-NEXT: [[OP_RDX5:%.*]] = fadd fast half [[OP_RDX2]], [[OP_RDX3]] +; VI-NEXT: [[OP_RDX6:%.*]] = fadd fast half [[OP_RDX4]], [[OP_RDX5]] +; VI-NEXT: [[OP_RDX7:%.*]] = fadd fast half [[OP_RDX6]], [[ELT15]] +; VI-NEXT: ret half [[OP_RDX7]] ; entry: %elt0 = extractelement <16 x half> %vec16, i64 0 @@ -183,21 +140,10 @@ entry: } define i16 @reduction_v4i16(<4 x i16> %a) { -; GFX9-LABEL: @reduction_v4i16( -; GFX9-NEXT: entry: -; GFX9-NEXT: [[TMP0:%.*]] = call i16 @llvm.vector.reduce.add.v4i16(<4 x i16> [[A:%.*]]) -; GFX9-NEXT: ret i16 [[TMP0]] -; -; VI-LABEL: @reduction_v4i16( -; VI-NEXT: entry: -; VI-NEXT: [[ELT0:%.*]] = extractelement <4 x i16> [[A:%.*]], i64 0 -; VI-NEXT: [[ELT1:%.*]] = extractelement <4 x i16> [[A]], i64 1 -; VI-NEXT: [[ELT2:%.*]] = extractelement <4 x i16> [[A]], i64 2 -; VI-NEXT: [[ELT3:%.*]] = extractelement <4 x i16> [[A]], i64 3 -; VI-NEXT: [[ADD1:%.*]] = add i16 [[ELT1]], [[ELT0]] -; VI-NEXT: [[ADD2:%.*]] = add i16 [[ELT2]], [[ADD1]] -; VI-NEXT: [[ADD3:%.*]] = add i16 [[ELT3]], [[ADD2]] -; VI-NEXT: ret i16 [[ADD3]] +; GCN-LABEL: @reduction_v4i16( +; GCN-NEXT: entry: +; GCN-NEXT: [[TMP0:%.*]] = call i16 @llvm.vector.reduce.add.v4i16(<4 x i16> [[A:%.*]]) +; GCN-NEXT: ret i16 [[TMP0]] ; entry: %elt0 = extractelement <4 x i16> %a, i64 0 @@ -213,29 +159,10 @@ entry: } define i16 @reduction_v8i16(<8 x i16> %vec8) { -; GFX9-LABEL: @reduction_v8i16( -; GFX9-NEXT: entry: -; GFX9-NEXT: [[TMP0:%.*]] = call i16 @llvm.vector.reduce.add.v8i16(<8 x i16> [[VEC8:%.*]]) -; GFX9-NEXT: ret i16 [[TMP0]] -; -; VI-LABEL: @reduction_v8i16( -; VI-NEXT: entry: -; VI-NEXT: [[ELT0:%.*]] = extractelement <8 x i16> [[VEC8:%.*]], i64 0 -; VI-NEXT: [[ELT1:%.*]] = extractelement <8 x i16> [[VEC8]], i64 1 -; VI-NEXT: [[ELT2:%.*]] = extractelement <8 x i16> [[VEC8]], i64 2 -; VI-NEXT: [[ELT3:%.*]] = extractelement <8 x i16> [[VEC8]], i64 3 -; VI-NEXT: [[ELT4:%.*]] = extractelement <8 x i16> [[VEC8]], i64 4 -; VI-NEXT: [[ELT5:%.*]] = extractelement <8 x i16> [[VEC8]], i64 5 -; VI-NEXT: [[ELT6:%.*]] = extractelement <8 x i16> [[VEC8]], i64 6 -; VI-NEXT: [[ELT7:%.*]] = extractelement <8 x i16> [[VEC8]], i64 7 -; VI-NEXT: [[ADD1:%.*]] = add i16 [[ELT1]], [[ELT0]] -; VI-NEXT: [[ADD2:%.*]] = add i16 [[ELT2]], [[ADD1]] -; VI-NEXT: [[ADD3:%.*]] = add i16 [[ELT3]], [[ADD2]] -; VI-NEXT: [[ADD4:%.*]] = add i16 [[ELT4]], [[ADD3]] -; VI-NEXT: [[ADD5:%.*]] = add i16 [[ELT5]], [[ADD4]] -; VI-NEXT: [[ADD6:%.*]] = add i16 [[ELT6]], [[ADD5]] -; VI-NEXT: [[ADD7:%.*]] = add i16 [[ELT7]], [[ADD6]] -; VI-NEXT: ret i16 [[ADD7]] +; GCN-LABEL: @reduction_v8i16( +; GCN-NEXT: entry: +; GCN-NEXT: [[TMP0:%.*]] = call i16 @llvm.vector.reduce.add.v8i16(<8 x i16> [[VEC8:%.*]]) +; GCN-NEXT: ret i16 [[TMP0]] ; entry: %elt0 = extractelement <8 x i16> %vec8, i64 0 -- GitLab From 446f66d685c2470bc7744b1d1538c4728e838e43 Mon Sep 17 00:00:00 2001 From: Fangrui Song Date: Tue, 21 May 2024 09:27:03 -0700 Subject: [PATCH 004/452] [CodeGen] Assign SHT_LLVM_LTO to .llvm.lto section (#92856) This follows up to SHT_LLVM_LTO (https://reviews.llvm.org/D153215) and resolves the comment of the FatLTO patch https://reviews.llvm.org/D146776#4430626 --- clang/test/CodeGen/fat-lto-objects.c | 2 +- llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp | 2 ++ llvm/test/CodeGen/X86/fat-lto-section.ll | 2 +- 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/clang/test/CodeGen/fat-lto-objects.c b/clang/test/CodeGen/fat-lto-objects.c index b50567c024fc..36a73684e7bf 100644 --- a/clang/test/CodeGen/fat-lto-objects.c +++ b/clang/test/CodeGen/fat-lto-objects.c @@ -62,7 +62,7 @@ // ELF: .llvm.lto -// ASM: .section .llvm.lto,"e",@progbits +// ASM: .section .llvm.lto,"e",@llvm_lto // ASM-NEXT: .Lllvm.embedded.object: // ASM-NEXT: .asciz "BC // ASM-NEXT: .size .Lllvm.embedded.object diff --git a/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp b/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp index 3e1897ce670a..0fc915d89f6c 100644 --- a/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp +++ b/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp @@ -523,6 +523,8 @@ static unsigned getELFSectionType(StringRef Name, SectionKind K) { if (hasPrefix(Name, ".llvm.offloading")) return ELF::SHT_LLVM_OFFLOADING; + if (Name == ".llvm.lto") + return ELF::SHT_LLVM_LTO; if (K.isBSS() || K.isThreadBSS()) return ELF::SHT_NOBITS; diff --git a/llvm/test/CodeGen/X86/fat-lto-section.ll b/llvm/test/CodeGen/X86/fat-lto-section.ll index 30c56229a0e2..f3ca8436affb 100644 --- a/llvm/test/CodeGen/X86/fat-lto-section.ll +++ b/llvm/test/CodeGen/X86/fat-lto-section.ll @@ -5,6 +5,6 @@ ; RUN: | FileCheck %s --check-prefix=EXCLUDE ; EXCLUDE: Name Type {{.*}} ES Flg Lk Inf Al -; EXCLUDE: .llvm.lto PROGBITS {{.*}} 00 E 0 0 1 +; EXCLUDE: .llvm.lto LLVM_LTO {{.*}} 00 E 0 0 1 @a = global i32 1 -- GitLab From cfeb25cd7e92d5e854aa92034f18da2e5fa3e27a Mon Sep 17 00:00:00 2001 From: John Brawn Date: Tue, 21 May 2024 17:34:17 +0100 Subject: [PATCH 005/452] [lld][AArch64] Add support for GCS (#90732) This adds the -z gcs and -z gcs-report options, which behave similarly to -z shtk and -z cet-report, except that -z gcs accepts a parameter: * -z gcs=implicit is the default behaviour, where the GCS bit is inferred from the input objects. * -z gcs=never clears the GCS bit, ignoring the input objects. * -z gcs=always sets the GCS bit, ignoring the input objects. This is so that there's a means of explicitly disabling GCS even when all input objects have the GCS bit set. --- lld/ELF/Config.h | 5 ++ lld/ELF/Driver.cpp | 36 ++++++++ lld/test/ELF/aarch64-feature-gcs.s | 134 +++++++++++++++++++++++++++++ 3 files changed, 175 insertions(+) create mode 100644 lld/test/ELF/aarch64-feature-gcs.s diff --git a/lld/ELF/Config.h b/lld/ELF/Config.h index dbb81412453a..f0dfe7f377de 100644 --- a/lld/ELF/Config.h +++ b/lld/ELF/Config.h @@ -102,6 +102,9 @@ enum class GnuStackKind { None, Exec, NoExec }; // For --lto= enum LtoKind : uint8_t {UnifiedThin, UnifiedRegular, Default}; +// For -z gcs= +enum class GcsPolicy { Implicit, Never, Always }; + struct SymbolVersion { llvm::StringRef name; bool isExternCpp; @@ -188,6 +191,7 @@ struct Config { StringRef zBtiReport = "none"; StringRef zCetReport = "none"; StringRef zPauthReport = "none"; + StringRef zGcsReport = "none"; bool ltoBBAddrMap; llvm::StringRef ltoBasicBlockSections; std::pair thinLTOObjectSuffixReplace; @@ -341,6 +345,7 @@ struct Config { UnresolvedPolicy unresolvedSymbols; UnresolvedPolicy unresolvedSymbolsInShlib; Target2Policy target2; + GcsPolicy zGcs; bool power10Stubs; ARMVFPArgKind armVFPArgs = ARMVFPArgKind::Default; BuildIdKind buildId = BuildIdKind::None; diff --git a/lld/ELF/Driver.cpp b/lld/ELF/Driver.cpp index 028cdcc83d2f..ddc574a11314 100644 --- a/lld/ELF/Driver.cpp +++ b/lld/ELF/Driver.cpp @@ -466,6 +466,10 @@ static void checkOptions() { error("-z bti-report only supported on AArch64"); if (config->zPauthReport != "none") error("-z pauth-report only supported on AArch64"); + if (config->zGcsReport != "none") + error("-z gcs-report only supported on AArch64"); + if (config->zGcs != GcsPolicy::Implicit) + error("-z gcs only supported on AArch64"); } if (config->emachine != EM_386 && config->emachine != EM_X86_64 && @@ -560,6 +564,25 @@ static uint8_t getZStartStopVisibility(opt::InputArgList &args) { return ret; } +static GcsPolicy getZGcs(opt::InputArgList &args) { + GcsPolicy ret = GcsPolicy::Implicit; + for (auto *arg : args.filtered(OPT_z)) { + std::pair kv = StringRef(arg->getValue()).split('='); + if (kv.first == "gcs") { + arg->claim(); + if (kv.second == "implicit") + ret = GcsPolicy::Implicit; + else if (kv.second == "never") + ret = GcsPolicy::Never; + else if (kv.second == "always") + ret = GcsPolicy::Always; + else + error("unknown -z gcs= value: " + kv.second); + } + } + return ret; +} + // Report a warning for an unknown -z option. static void checkZOptions(opt::InputArgList &args) { // This function is called before getTarget(), when certain options are not @@ -1438,6 +1461,7 @@ static void readConfigs(opt::InputArgList &args) { config->zCopyreloc = getZFlag(args, "copyreloc", "nocopyreloc", true); config->zForceBti = hasZOption(args, "force-bti"); config->zForceIbt = hasZOption(args, "force-ibt"); + config->zGcs = getZGcs(args); config->zGlobal = hasZOption(args, "global"); config->zGnustack = getZGnuStack(args); config->zHazardplt = hasZOption(args, "hazardplt"); @@ -1510,6 +1534,7 @@ static void readConfigs(opt::InputArgList &args) { auto reports = {std::make_pair("bti-report", &config->zBtiReport), std::make_pair("cet-report", &config->zCetReport), + std::make_pair("gcs-report", &config->zGcsReport), std::make_pair("pauth-report", &config->zPauthReport)}; for (opt::Arg *arg : args.filtered(OPT_z)) { std::pair option = @@ -2677,6 +2702,11 @@ static void readSecurityNotes() { toString(f) + ": -z bti-report: file does not have " "GNU_PROPERTY_AARCH64_FEATURE_1_BTI property"); + checkAndReportMissingFeature( + config->zGcsReport, features, GNU_PROPERTY_AARCH64_FEATURE_1_GCS, + toString(f) + ": -z gcs-report: file does not have " + "GNU_PROPERTY_AARCH64_FEATURE_1_GCS property"); + checkAndReportMissingFeature( config->zCetReport, features, GNU_PROPERTY_X86_FEATURE_1_IBT, toString(f) + ": -z cet-report: file does not have " @@ -2729,6 +2759,12 @@ static void readSecurityNotes() { // Force enable Shadow Stack. if (config->zShstk) config->andFeatures |= GNU_PROPERTY_X86_FEATURE_1_SHSTK; + + // Force enable/disable GCS + if (config->zGcs == GcsPolicy::Always) + config->andFeatures |= GNU_PROPERTY_AARCH64_FEATURE_1_GCS; + else if (config->zGcs == GcsPolicy::Never) + config->andFeatures &= ~GNU_PROPERTY_AARCH64_FEATURE_1_GCS; } static void initSectionsAndLocalSyms(ELFFileBase *file, bool ignoreComdats) { diff --git a/lld/test/ELF/aarch64-feature-gcs.s b/lld/test/ELF/aarch64-feature-gcs.s new file mode 100644 index 000000000000..7a08673dbb7e --- /dev/null +++ b/lld/test/ELF/aarch64-feature-gcs.s @@ -0,0 +1,134 @@ +# REQUIRES: aarch64 +# RUN: rm -rf %t && split-file %s %t && cd %t +# RUN: llvm-mc -filetype=obj -triple=aarch64-linux-gnu func1-gcs.s -o func1-gcs.o +# RUN: llvm-mc -filetype=obj -triple=aarch64-linux-gnu func2.s -o func2.o +# RUN: llvm-mc -filetype=obj -triple=aarch64-linux-gnu func2-gcs.s -o func2-gcs.o +# RUN: llvm-mc -filetype=obj -triple=aarch64-linux-gnu func3.s -o func3.o +# RUN: llvm-mc -filetype=obj -triple=aarch64-linux-gnu func3-gcs.s -o func3-gcs.o + +## GCS should be enabled when it's enabled in all inputs or when it's forced on. + +# RUN: ld.lld func1-gcs.o func2-gcs.o func3-gcs.o -o gcs +# RUN: llvm-readelf -n gcs | FileCheck --check-prefix GCS %s +# RUN: ld.lld func1-gcs.o func3-gcs.o --shared -o gcs.so +# RUN: llvm-readelf -n gcs.so | FileCheck --check-prefix GCS %s +# RUN: ld.lld func1-gcs.o func2.o func3-gcs.o -o force-gcs -z gcs=always +# RUN: llvm-readelf -n force-gcs | FileCheck --check-prefix GCS %s +# RUN: ld.lld func2-gcs.o func3.o --shared -o force-gcs.so -z gcs=always +# RUN: llvm-readelf -n force-gcs.so | FileCheck --check-prefix GCS %s +# RUN: ld.lld func2-gcs.o func3.o --shared -o force-gcs2.so -z gcs=never -z gcs=always +# RUN: llvm-readelf -n force-gcs2.so | FileCheck --check-prefix GCS %s + +# GCS: Properties: aarch64 feature: GCS + +## GCS should not be enabled if it's not enabled in at least one input. + +# RUN: ld.lld func1-gcs.o func2.o func3-gcs.o -o no-gcs +# RUN: llvm-readelf -n no-gcs | count 0 +# RUN: ld.lld func2-gcs.o func3.o --shared -o no-gcs.so + +## GCS should be disabled with gcs=never, even if GCS is present in all inputs. + +# RUN: ld.lld func1-gcs.o func2-gcs.o func3-gcs.o -z gcs=never -o never-gcs +# RUN: llvm-readelf -n never-gcs | count 0 +# RUN: ld.lld func1-gcs.o func2-gcs.o func3-gcs.o -z gcs=always -z gcs=never -o never-gcs2 +# RUN: llvm-readelf -n never-gcs2 | count 0 + +## gcs-report should report any input files that don't have the gcs property. + +# RUN: ld.lld func1-gcs.o func2.o func3-gcs.o -o /dev/null -z gcs-report=warning 2>&1 | FileCheck --check-prefix=REPORT-WARN %s +# RUN: ld.lld func1-gcs.o func2.o func3-gcs.o -o /dev/null -z gcs-report=warning -z gcs=always 2>&1 | FileCheck --check-prefix=REPORT-WARN %s +# RUN: ld.lld func1-gcs.o func2.o func3-gcs.o -o /dev/null -z gcs-report=warning -z gcs=never 2>&1 | FileCheck --check-prefix=REPORT-WARN %s +# RUN: not ld.lld func2-gcs.o func3.o --shared -o /dev/null -z gcs-report=error 2>&1 | FileCheck --check-prefix=REPORT-ERROR %s +# RUN: not ld.lld func2-gcs.o func3.o --shared -o /dev/null -z gcs-report=error -z gcs=always 2>&1 | FileCheck --check-prefix=REPORT-ERROR %s +# RUN: not ld.lld func2-gcs.o func3.o --shared -o /dev/null -z gcs-report=error -z gcs=never 2>&1 | FileCheck --check-prefix=REPORT-ERROR %s +# RUN: ld.lld func1-gcs.o func2-gcs.o func3-gcs.o -o /dev/null -z gcs-report=warning 2>&1 | count 0 +# RUN: ld.lld func1-gcs.o func2-gcs.o func3-gcs.o -o /dev/null -z gcs-report=warning -z gcs=always 2>&1 | count 0 +# RUN: ld.lld func1-gcs.o func2-gcs.o func3-gcs.o -o /dev/null -z gcs-report=warning -z gcs=never 2>&1 | count 0 + +# REPORT-WARN: warning: func2.o: -z gcs-report: file does not have GNU_PROPERTY_AARCH64_FEATURE_1_GCS property +# REPORT-ERROR: error: func3.o: -z gcs-report: file does not have GNU_PROPERTY_AARCH64_FEATURE_1_GCS property + +## An invalid gcs option should give an error +# RUN: not ld.lld func1-gcs.o func2-gcs.o func3-gcs.o -z gcs=nonsense 2>&1 | FileCheck --check-prefix=INVALID %s + +# INVALID: error: unknown -z gcs= value: nonsense + +#--- func1-gcs.s +.section ".note.gnu.property", "a" +.long 4 +.long 0x10 +.long 0x5 +.asciz "GNU" + +.long 0xc0000000 // GNU_PROPERTY_AARCH64_FEATURE_1_AND +.long 4 +.long 4 // GNU_PROPERTY_AARCH64_FEATURE_1_GCS +.long 0 + +.text +.globl _start +.type func1,%function +func1: + bl func2 + ret + +#--- func2.s + +.text +.globl func2 +.type func2,@function +func2: + .globl func3 + .type func3, @function + bl func3 + ret + +#--- func2-gcs.s + +.section ".note.gnu.property", "a" +.long 4 +.long 0x10 +.long 0x5 +.asciz "GNU" + +.long 0xc0000000 // GNU_PROPERTY_AARCH64_FEATURE_1_AND +.long 4 +.long 4 // GNU_PROPERTY_AARCH64_FEATURE_1_GCS +.long 0 + +.text +.globl func2 +.type func2,@function +func2: + .globl func3 + .type func3, @function + bl func3 + ret + +#--- func3.s + +.text +.globl func3 +.type func3,@function +func3: + ret + +#--- func3-gcs.s + +.section ".note.gnu.property", "a" +.long 4 +.long 0x10 +.long 0x5 +.asciz "GNU" + +.long 0xc0000000 // GNU_PROPERTY_AARCH64_FEATURE_1_AND +.long 4 +.long 4 // GNU_PROPERTY_AARCH64_FEATURE_1_GCS +.long 0 + +.text +.globl func3 +.type func3,@function +func3: + ret -- GitLab From 67e3514692f60f85c69aef9a793d3e43b68fb038 Mon Sep 17 00:00:00 2001 From: Matt Arsenault Date: Tue, 21 May 2024 18:41:32 +0200 Subject: [PATCH 006/452] AMDGPU: Implement getRoundingControlRegisters (#92884) --- llvm/lib/Target/AMDGPU/SIISelLowering.cpp | 5 ++ llvm/lib/Target/AMDGPU/SIISelLowering.h | 2 + .../CodeGen/AMDGPU/call-defs-mode-register.ll | 57 +++++++++++++++++++ 3 files changed, 64 insertions(+) create mode 100644 llvm/test/CodeGen/AMDGPU/call-defs-mode-register.ll diff --git a/llvm/lib/Target/AMDGPU/SIISelLowering.cpp b/llvm/lib/Target/AMDGPU/SIISelLowering.cpp index 42e1c1ce764c..45a16a14996e 100644 --- a/llvm/lib/Target/AMDGPU/SIISelLowering.cpp +++ b/llvm/lib/Target/AMDGPU/SIISelLowering.cpp @@ -957,6 +957,11 @@ const GCNSubtarget *SITargetLowering::getSubtarget() const { return Subtarget; } +ArrayRef SITargetLowering::getRoundingControlRegisters() const { + static const MCPhysReg RCRegs[] = {AMDGPU::MODE}; + return RCRegs; +} + //===----------------------------------------------------------------------===// // TargetLowering queries //===----------------------------------------------------------------------===// diff --git a/llvm/lib/Target/AMDGPU/SIISelLowering.h b/llvm/lib/Target/AMDGPU/SIISelLowering.h index 08aa2a599163..fed73f48840f 100644 --- a/llvm/lib/Target/AMDGPU/SIISelLowering.h +++ b/llvm/lib/Target/AMDGPU/SIISelLowering.h @@ -287,6 +287,8 @@ public: const GCNSubtarget *getSubtarget() const; + ArrayRef getRoundingControlRegisters() const override; + bool isFPExtFoldable(const SelectionDAG &DAG, unsigned Opcode, EVT DestVT, EVT SrcVT) const override; diff --git a/llvm/test/CodeGen/AMDGPU/call-defs-mode-register.ll b/llvm/test/CodeGen/AMDGPU/call-defs-mode-register.ll new file mode 100644 index 000000000000..7ad24302d783 --- /dev/null +++ b/llvm/test/CodeGen/AMDGPU/call-defs-mode-register.ll @@ -0,0 +1,57 @@ +; NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py UTC_ARGS: --version 5 +; RUN: llc -mtriple=amdgcn-amd-amdhsa -mcpu=gfx900 -simplify-mir -stop-after=finalize-isel < %s | FileCheck %s + +; Check that call / asm get an implicit-def $mode added to them in +; strictfp functions. + +declare protected void @maybe_defs_mode() #0 + +define float @call_changes_mode(float %x, float %y) #0 { + ; CHECK-LABEL: name: call_changes_mode + ; CHECK: bb.0 (%ir-block.0): + ; CHECK-NEXT: liveins: $vgpr0, $vgpr1 + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: [[COPY:%[0-9]+]]:vgpr_32 = COPY $vgpr1 + ; CHECK-NEXT: [[COPY1:%[0-9]+]]:vgpr_32 = COPY $vgpr0 + ; CHECK-NEXT: ADJCALLSTACKUP 0, 0, implicit-def dead $scc, implicit-def $sgpr32, implicit $sgpr32 + ; CHECK-NEXT: [[SI_PC_ADD_REL_OFFSET:%[0-9]+]]:sreg_64 = SI_PC_ADD_REL_OFFSET target-flags(amdgpu-rel32-lo) @maybe_defs_mode, target-flags(amdgpu-rel32-hi) @maybe_defs_mode, implicit-def dead $scc + ; CHECK-NEXT: [[COPY2:%[0-9]+]]:sgpr_128 = COPY $sgpr0_sgpr1_sgpr2_sgpr3 + ; CHECK-NEXT: $sgpr0_sgpr1_sgpr2_sgpr3 = COPY [[COPY2]] + ; CHECK-NEXT: $sgpr30_sgpr31 = SI_CALL killed [[SI_PC_ADD_REL_OFFSET]], @maybe_defs_mode, csr_amdgpu, implicit $sgpr0_sgpr1_sgpr2_sgpr3, implicit-def $mode + ; CHECK-NEXT: ADJCALLSTACKDOWN 0, 0, implicit-def dead $scc, implicit-def $sgpr32, implicit $sgpr32 + ; CHECK-NEXT: [[V_ADD_F32_e64_:%[0-9]+]]:vgpr_32 = nofpexcept V_ADD_F32_e64 0, [[COPY1]], 0, [[COPY]], 0, 0, implicit $mode, implicit $exec + ; CHECK-NEXT: $vgpr0 = COPY [[V_ADD_F32_e64_]] + ; CHECK-NEXT: SI_RETURN implicit $vgpr0 + call void @maybe_defs_mode() + %val = call float @llvm.experimental.constrained.fadd.f32(float %x, float %y, metadata !"round.dynamic", metadata !"fpexcept.ignore") + ret float %val +} + +define void @tail_call_changes_mode() #0 { + ; CHECK-LABEL: name: tail_call_changes_mode + ; CHECK: bb.0 (%ir-block.0): + ; CHECK-NEXT: [[SI_PC_ADD_REL_OFFSET:%[0-9]+]]:ccr_sgpr_64 = SI_PC_ADD_REL_OFFSET target-flags(amdgpu-rel32-lo) @maybe_defs_mode, target-flags(amdgpu-rel32-hi) @maybe_defs_mode, implicit-def dead $scc + ; CHECK-NEXT: SI_TCRETURN killed [[SI_PC_ADD_REL_OFFSET]], @maybe_defs_mode, 0, csr_amdgpu, implicit-def $mode + tail call void @maybe_defs_mode() + ret void +} + +define float @asm_changes_mode(float %x, float %y) #0 { + ; CHECK-LABEL: name: asm_changes_mode + ; CHECK: bb.0 (%ir-block.0): + ; CHECK-NEXT: liveins: $vgpr0, $vgpr1 + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: [[COPY:%[0-9]+]]:vgpr_32 = COPY $vgpr1 + ; CHECK-NEXT: [[COPY1:%[0-9]+]]:vgpr_32 = COPY $vgpr0 + ; CHECK-NEXT: INLINEASM &"; maybe defs mode", 1 /* sideeffect attdialect */ + ; CHECK-NEXT: [[V_ADD_F32_e64_:%[0-9]+]]:vgpr_32 = nofpexcept V_ADD_F32_e64 0, [[COPY1]], 0, [[COPY]], 0, 0, implicit $mode, implicit $exec + ; CHECK-NEXT: $vgpr0 = COPY [[V_ADD_F32_e64_]] + ; CHECK-NEXT: SI_RETURN implicit $vgpr0 + call void asm sideeffect "; maybe defs mode", ""() + %val = call float @llvm.experimental.constrained.fadd.f32(float %x, float %y, metadata !"round.dynamic", metadata !"fpexcept.ignore") + ret float %val +} + +declare float @llvm.experimental.constrained.fadd.f32(float, float, metadata, metadata) + +attributes #0 = { strictfp "amdgpu-no-completion-action" "amdgpu-no-default-queue" "amdgpu-no-dispatch-id" "amdgpu-no-dispatch-ptr" "amdgpu-no-heap-ptr" "amdgpu-no-hostcall-ptr" "amdgpu-no-implicitarg-ptr" "amdgpu-no-lds-kernel-id" "amdgpu-no-multigrid-sync-arg" "amdgpu-no-queue-ptr" "amdgpu-no-workgroup-id-x" "amdgpu-no-workgroup-id-y" "amdgpu-no-workgroup-id-z" "amdgpu-no-workitem-id-x" "amdgpu-no-workitem-id-y" "amdgpu-no-workitem-id-z" } -- GitLab From dab1f7c8d3d7bf5021cdb96af74d533753ad2e23 Mon Sep 17 00:00:00 2001 From: Matt Arsenault Date: Tue, 21 May 2024 18:42:45 +0200 Subject: [PATCH 007/452] AMDGPU: Emit 1/llvm.sqrt(x) instead of rsqrt calls in libcall handling (#92863) With the contract flag we should end up codegening to the rsqrt instruction, or denormal corrected rsqrt sequence present in the library. --- llvm/lib/Target/AMDGPU/AMDGPULibCalls.cpp | 38 ++++++++++++---- .../AMDGPU/amdgpu-simplify-libcall-rootn.ll | 43 +++++++++++-------- llvm/test/CodeGen/AMDGPU/simplify-libcalls.ll | 4 +- 3 files changed, 56 insertions(+), 29 deletions(-) diff --git a/llvm/lib/Target/AMDGPU/AMDGPULibCalls.cpp b/llvm/lib/Target/AMDGPU/AMDGPULibCalls.cpp index aab79ceb57f2..c515138d95a2 100644 --- a/llvm/lib/Target/AMDGPU/AMDGPULibCalls.cpp +++ b/llvm/lib/Target/AMDGPU/AMDGPULibCalls.cpp @@ -1215,16 +1215,36 @@ bool AMDGPULibCalls::fold_rootn(FPMathOperator *FPOp, IRBuilder<> &B, "__rootn2div"); replaceCall(FPOp, nval); return true; - } else if (ci_opr1 == -2) { // rootn(x, -2) = rsqrt(x) - if (FunctionCallee FPExpr = - getFunction(M, AMDGPULibFunc(AMDGPULibFunc::EI_RSQRT, FInfo))) { - LLVM_DEBUG(errs() << "AMDIC: " << *FPOp << " ---> rsqrt(" << *opr0 - << ")\n"); - Value *nval = CreateCallEx(B,FPExpr, opr0, "__rootn2rsqrt"); - replaceCall(FPOp, nval); - return true; - } } + + if (ci_opr1 == -2 && + shouldReplaceLibcallWithIntrinsic(CI, + /*AllowMinSizeF32=*/true, + /*AllowF64=*/true)) { + // rootn(x, -2) = rsqrt(x) + + // The original rootn had looser ulp requirements than the resultant sqrt + // and fdiv. + MDBuilder MDHelper(M->getContext()); + MDNode *FPMD = MDHelper.createFPMath(std::max(FPOp->getFPAccuracy(), 2.0f)); + + // TODO: Could handle strictfp but need to fix strict sqrt emission + FastMathFlags FMF = FPOp->getFastMathFlags(); + FMF.setAllowContract(true); + + CallInst *Sqrt = B.CreateUnaryIntrinsic(Intrinsic::sqrt, opr0, CI); + Instruction *RSqrt = cast( + B.CreateFDiv(ConstantFP::get(opr0->getType(), 1.0), Sqrt)); + Sqrt->setFastMathFlags(FMF); + RSqrt->setFastMathFlags(FMF); + RSqrt->setMetadata(LLVMContext::MD_fpmath, FPMD); + + LLVM_DEBUG(errs() << "AMDIC: " << *FPOp << " ---> rsqrt(" << *opr0 + << ")\n"); + replaceCall(CI, RSqrt); + return true; + } + return false; } diff --git a/llvm/test/CodeGen/AMDGPU/amdgpu-simplify-libcall-rootn.ll b/llvm/test/CodeGen/AMDGPU/amdgpu-simplify-libcall-rootn.ll index c105ad7590e6..7932f8d1fc5b 100644 --- a/llvm/test/CodeGen/AMDGPU/amdgpu-simplify-libcall-rootn.ll +++ b/llvm/test/CodeGen/AMDGPU/amdgpu-simplify-libcall-rootn.ll @@ -302,7 +302,8 @@ define half @test_rootn_f16_neg1(half %x) { define half @test_rootn_f16_neg2(half %x) { ; CHECK-LABEL: define half @test_rootn_f16_neg2( ; CHECK-SAME: half [[X:%.*]]) { -; CHECK-NEXT: [[__ROOTN2RSQRT:%.*]] = call half @_Z5rsqrtDh(half [[X]]) +; CHECK-NEXT: [[TMP1:%.*]] = call contract half @llvm.sqrt.f16(half [[X]]) +; CHECK-NEXT: [[__ROOTN2RSQRT:%.*]] = fdiv contract half 0xH3C00, [[TMP1]], !fpmath [[META0]] ; CHECK-NEXT: ret half [[__ROOTN2RSQRT]] ; %call = tail call half @_Z5rootnDhi(half %x, i32 -2) @@ -371,7 +372,8 @@ define <2 x half> @test_rootn_v2f16_neg1(<2 x half> %x) { define <2 x half> @test_rootn_v2f16_neg2(<2 x half> %x) { ; CHECK-LABEL: define <2 x half> @test_rootn_v2f16_neg2( ; CHECK-SAME: <2 x half> [[X:%.*]]) { -; CHECK-NEXT: [[__ROOTN2RSQRT:%.*]] = call <2 x half> @_Z5rsqrtDv2_Dh(<2 x half> [[X]]) +; CHECK-NEXT: [[TMP1:%.*]] = call contract <2 x half> @llvm.sqrt.v2f16(<2 x half> [[X]]) +; CHECK-NEXT: [[__ROOTN2RSQRT:%.*]] = fdiv contract <2 x half> , [[TMP1]], !fpmath [[META0]] ; CHECK-NEXT: ret <2 x half> [[__ROOTN2RSQRT]] ; %call = tail call <2 x half> @_Z5rootnDv2_DhDv2_i(<2 x half> %x, <2 x i32> ) @@ -865,7 +867,8 @@ define float @test_rootn_f32__y_neg2(float %x) { ; CHECK-LABEL: define float @test_rootn_f32__y_neg2( ; CHECK-SAME: float [[X:%.*]]) { ; CHECK-NEXT: entry: -; CHECK-NEXT: [[__ROOTN2RSQRT:%.*]] = call float @_Z5rsqrtf(float [[X]]) +; CHECK-NEXT: [[TMP0:%.*]] = call contract float @llvm.sqrt.f32(float [[X]]) +; CHECK-NEXT: [[__ROOTN2RSQRT:%.*]] = fdiv contract float 1.000000e+00, [[TMP0]], !fpmath [[META0]] ; CHECK-NEXT: ret float [[__ROOTN2RSQRT]] ; entry: @@ -877,7 +880,8 @@ define float @test_rootn_f32__y_neg2__flags(float %x) { ; CHECK-LABEL: define float @test_rootn_f32__y_neg2__flags( ; CHECK-SAME: float [[X:%.*]]) { ; CHECK-NEXT: entry: -; CHECK-NEXT: [[__ROOTN2RSQRT:%.*]] = call nnan nsz float @_Z5rsqrtf(float [[X]]) +; CHECK-NEXT: [[TMP0:%.*]] = call nnan nsz contract float @llvm.sqrt.f32(float [[X]]) +; CHECK-NEXT: [[__ROOTN2RSQRT:%.*]] = fdiv nnan nsz contract float 1.000000e+00, [[TMP0]], !fpmath [[META0]] ; CHECK-NEXT: ret float [[__ROOTN2RSQRT]] ; entry: @@ -889,7 +893,7 @@ define float @test_rootn_f32__y_neg2__strictfp(float %x) #1 { ; CHECK-LABEL: define float @test_rootn_f32__y_neg2__strictfp( ; CHECK-SAME: float [[X:%.*]]) #[[ATTR0]] { ; CHECK-NEXT: entry: -; CHECK-NEXT: [[__ROOTN2RSQRT:%.*]] = call float @_Z5rsqrtf(float [[X]]) #[[ATTR0]] +; CHECK-NEXT: [[__ROOTN2RSQRT:%.*]] = tail call float @_Z5rootnfi(float [[X]], i32 -2) #[[ATTR0]] ; CHECK-NEXT: ret float [[__ROOTN2RSQRT]] ; entry: @@ -901,7 +905,7 @@ define float @test_rootn_f32__y_neg2__noinline(float %x) { ; CHECK-LABEL: define float @test_rootn_f32__y_neg2__noinline( ; CHECK-SAME: float [[X:%.*]]) { ; CHECK-NEXT: entry: -; CHECK-NEXT: [[__ROOTN2RSQRT:%.*]] = call float @_Z5rsqrtf(float [[X]]) +; CHECK-NEXT: [[__ROOTN2RSQRT:%.*]] = tail call float @_Z5rootnfi(float [[X]], i32 -2) #[[ATTR3:[0-9]+]] ; CHECK-NEXT: ret float [[__ROOTN2RSQRT]] ; entry: @@ -913,7 +917,7 @@ define float @test_rootn_f32__y_neg2__nobuiltin(float %x) { ; CHECK-LABEL: define float @test_rootn_f32__y_neg2__nobuiltin( ; CHECK-SAME: float [[X:%.*]]) { ; CHECK-NEXT: entry: -; CHECK-NEXT: [[CALL:%.*]] = tail call float @_Z5rootnfi(float [[X]], i32 -2) #[[ATTR3:[0-9]+]] +; CHECK-NEXT: [[CALL:%.*]] = tail call float @_Z5rootnfi(float [[X]], i32 -2) #[[ATTR4:[0-9]+]] ; CHECK-NEXT: ret float [[CALL]] ; entry: @@ -925,7 +929,8 @@ define <2 x float> @test_rootn_v2f32__y_neg2(<2 x float> %x) { ; CHECK-LABEL: define <2 x float> @test_rootn_v2f32__y_neg2( ; CHECK-SAME: <2 x float> [[X:%.*]]) { ; CHECK-NEXT: entry: -; CHECK-NEXT: [[__ROOTN2RSQRT:%.*]] = call <2 x float> @_Z5rsqrtDv2_f(<2 x float> [[X]]) +; CHECK-NEXT: [[TMP0:%.*]] = call contract <2 x float> @llvm.sqrt.v2f32(<2 x float> [[X]]) +; CHECK-NEXT: [[__ROOTN2RSQRT:%.*]] = fdiv contract <2 x float> , [[TMP0]], !fpmath [[META0]] ; CHECK-NEXT: ret <2 x float> [[__ROOTN2RSQRT]] ; entry: @@ -937,7 +942,8 @@ define <2 x float> @test_rootn_v2f32__y_neg2__flags(<2 x float> %x) { ; CHECK-LABEL: define <2 x float> @test_rootn_v2f32__y_neg2__flags( ; CHECK-SAME: <2 x float> [[X:%.*]]) { ; CHECK-NEXT: entry: -; CHECK-NEXT: [[__ROOTN2RSQRT:%.*]] = call nnan nsz <2 x float> @_Z5rsqrtDv2_f(<2 x float> [[X]]) +; CHECK-NEXT: [[TMP0:%.*]] = call nnan nsz contract <2 x float> @llvm.sqrt.v2f32(<2 x float> [[X]]) +; CHECK-NEXT: [[__ROOTN2RSQRT:%.*]] = fdiv nnan nsz contract <2 x float> , [[TMP0]], !fpmath [[META0]] ; CHECK-NEXT: ret <2 x float> [[__ROOTN2RSQRT]] ; entry: @@ -949,7 +955,7 @@ define <2 x float> @test_rootn_v2f32__y_neg2__strictfp(<2 x float> %x) #1 { ; CHECK-LABEL: define <2 x float> @test_rootn_v2f32__y_neg2__strictfp( ; CHECK-SAME: <2 x float> [[X:%.*]]) #[[ATTR0]] { ; CHECK-NEXT: entry: -; CHECK-NEXT: [[__ROOTN2RSQRT:%.*]] = call <2 x float> @_Z5rsqrtDv2_f(<2 x float> [[X]]) #[[ATTR0]] +; CHECK-NEXT: [[__ROOTN2RSQRT:%.*]] = tail call <2 x float> @_Z5rootnDv2_fDv2_i(<2 x float> [[X]], <2 x i32> ) #[[ATTR0]] ; CHECK-NEXT: ret <2 x float> [[__ROOTN2RSQRT]] ; entry: @@ -1125,7 +1131,7 @@ define float @test_rootn_fast_f32_nobuiltin(float %x, i32 %y) { ; CHECK-LABEL: define float @test_rootn_fast_f32_nobuiltin( ; CHECK-SAME: float [[X:%.*]], i32 [[Y:%.*]]) { ; CHECK-NEXT: entry: -; CHECK-NEXT: [[CALL:%.*]] = tail call fast float @_Z5rootnfi(float [[X]], i32 [[Y]]) #[[ATTR3]] +; CHECK-NEXT: [[CALL:%.*]] = tail call fast float @_Z5rootnfi(float [[X]], i32 [[Y]]) #[[ATTR4]] ; CHECK-NEXT: ret float [[CALL]] ; entry: @@ -1420,7 +1426,7 @@ entry: define float @test_rootn_f32__y_0_nobuiltin(float %x) { ; CHECK-LABEL: define float @test_rootn_f32__y_0_nobuiltin( ; CHECK-SAME: float [[X:%.*]]) { -; CHECK-NEXT: [[CALL:%.*]] = tail call float @_Z5rootnfi(float [[X]], i32 0) #[[ATTR3]] +; CHECK-NEXT: [[CALL:%.*]] = tail call float @_Z5rootnfi(float [[X]], i32 0) #[[ATTR4]] ; CHECK-NEXT: ret float [[CALL]] ; %call = tail call float @_Z5rootnfi(float %x, i32 0) #0 @@ -1430,7 +1436,7 @@ define float @test_rootn_f32__y_0_nobuiltin(float %x) { define float @test_rootn_f32__y_1_nobuiltin(float %x) { ; CHECK-LABEL: define float @test_rootn_f32__y_1_nobuiltin( ; CHECK-SAME: float [[X:%.*]]) { -; CHECK-NEXT: [[CALL:%.*]] = tail call float @_Z5rootnfi(float [[X]], i32 1) #[[ATTR3]] +; CHECK-NEXT: [[CALL:%.*]] = tail call float @_Z5rootnfi(float [[X]], i32 1) #[[ATTR4]] ; CHECK-NEXT: ret float [[CALL]] ; %call = tail call float @_Z5rootnfi(float %x, i32 1) #0 @@ -1440,7 +1446,7 @@ define float @test_rootn_f32__y_1_nobuiltin(float %x) { define float @test_rootn_f32__y_2_nobuiltin(float %x) { ; CHECK-LABEL: define float @test_rootn_f32__y_2_nobuiltin( ; CHECK-SAME: float [[X:%.*]]) { -; CHECK-NEXT: [[CALL:%.*]] = tail call float @_Z5rootnfi(float [[X]], i32 2) #[[ATTR3]] +; CHECK-NEXT: [[CALL:%.*]] = tail call float @_Z5rootnfi(float [[X]], i32 2) #[[ATTR4]] ; CHECK-NEXT: ret float [[CALL]] ; %call = tail call float @_Z5rootnfi(float %x, i32 2) #0 @@ -1450,7 +1456,7 @@ define float @test_rootn_f32__y_2_nobuiltin(float %x) { define float @test_rootn_f32__y_3_nobuiltin(float %x) { ; CHECK-LABEL: define float @test_rootn_f32__y_3_nobuiltin( ; CHECK-SAME: float [[X:%.*]]) { -; CHECK-NEXT: [[CALL:%.*]] = tail call float @_Z5rootnfi(float [[X]], i32 3) #[[ATTR3]] +; CHECK-NEXT: [[CALL:%.*]] = tail call float @_Z5rootnfi(float [[X]], i32 3) #[[ATTR4]] ; CHECK-NEXT: ret float [[CALL]] ; %call = tail call float @_Z5rootnfi(float %x, i32 3) #0 @@ -1460,7 +1466,7 @@ define float @test_rootn_f32__y_3_nobuiltin(float %x) { define float @test_rootn_f32__y_neg1_nobuiltin(float %x) { ; CHECK-LABEL: define float @test_rootn_f32__y_neg1_nobuiltin( ; CHECK-SAME: float [[X:%.*]]) { -; CHECK-NEXT: [[CALL:%.*]] = tail call float @_Z5rootnfi(float [[X]], i32 -1) #[[ATTR3]] +; CHECK-NEXT: [[CALL:%.*]] = tail call float @_Z5rootnfi(float [[X]], i32 -1) #[[ATTR4]] ; CHECK-NEXT: ret float [[CALL]] ; %call = tail call float @_Z5rootnfi(float %x, i32 -1) #0 @@ -1470,7 +1476,7 @@ define float @test_rootn_f32__y_neg1_nobuiltin(float %x) { define float @test_rootn_f32__y_neg2_nobuiltin(float %x) { ; CHECK-LABEL: define float @test_rootn_f32__y_neg2_nobuiltin( ; CHECK-SAME: float [[X:%.*]]) { -; CHECK-NEXT: [[CALL:%.*]] = tail call float @_Z5rootnfi(float [[X]], i32 -2) #[[ATTR3]] +; CHECK-NEXT: [[CALL:%.*]] = tail call float @_Z5rootnfi(float [[X]], i32 -2) #[[ATTR4]] ; CHECK-NEXT: ret float [[CALL]] ; %call = tail call float @_Z5rootnfi(float %x, i32 -2) #0 @@ -1487,7 +1493,8 @@ attributes #2 = { noinline } ; CHECK: attributes #[[ATTR0]] = { strictfp } ; CHECK: attributes #[[ATTR1:[0-9]+]] = { nocallback nofree nosync nounwind speculatable willreturn memory(none) } ; CHECK: attributes #[[ATTR2:[0-9]+]] = { nounwind memory(read) } -; CHECK: attributes #[[ATTR3]] = { nobuiltin } +; CHECK: attributes #[[ATTR3]] = { noinline } +; CHECK: attributes #[[ATTR4]] = { nobuiltin } ;. ; CHECK: [[META0]] = !{float 2.000000e+00} ; CHECK: [[META1]] = !{float 3.000000e+00} diff --git a/llvm/test/CodeGen/AMDGPU/simplify-libcalls.ll b/llvm/test/CodeGen/AMDGPU/simplify-libcalls.ll index 152eba5dec94..5a241f85b2e2 100644 --- a/llvm/test/CodeGen/AMDGPU/simplify-libcalls.ll +++ b/llvm/test/CodeGen/AMDGPU/simplify-libcalls.ll @@ -506,8 +506,8 @@ entry: } ; GCN-LABEL: {{^}}define amdgpu_kernel void @test_rootn_m2 -; GCN-POSTLINK: call fast float @_Z5rootnfi(float %tmp, i32 -2) -; GCN-PRELINK: %__rootn2rsqrt = tail call fast float @_Z5rsqrtf(float %tmp) +; GCN: [[SQRT:%.+]] = tail call fast float @llvm.sqrt.f32(float %tmp) +; GCN-NEXT: fdiv fast float 1.000000e+00, [[SQRT]] define amdgpu_kernel void @test_rootn_m2(ptr addrspace(1) nocapture %a) { entry: %tmp = load float, ptr addrspace(1) %a, align 4 -- GitLab From 0c8bc08868e7bf051e9683851726747def85765a Mon Sep 17 00:00:00 2001 From: Alan Zhao Date: Tue, 21 May 2024 09:48:03 -0700 Subject: [PATCH 008/452] Reapply "[coro][CoroSplit] Use `llvm.lifetime.end` to compute putting objects on the frame vs the stack (#90265) (#91372) This reverts commit 924384161ffceda08099536dd07a953299a69b53. This reland addresses the performance regressions seen in #90265 by retaining the original definition of `isPotentiallyReachableFromMany(...)` instead of reimplementing it with `isManyPotentiallyReachableFromMany(...)`. Fixes #86580 --- llvm/include/llvm/Analysis/CFG.h | 12 ++ llvm/lib/Analysis/CFG.cpp | 74 +++++++-- llvm/lib/Transforms/Coroutines/CoroFrame.cpp | 60 +++++--- .../Coroutines/coro-lifetime-end.ll | 142 ++++++++++++++++++ 4 files changed, 259 insertions(+), 29 deletions(-) create mode 100644 llvm/test/Transforms/Coroutines/coro-lifetime-end.ll diff --git a/llvm/include/llvm/Analysis/CFG.h b/llvm/include/llvm/Analysis/CFG.h index 86b01c13274f..23bc10a4a9d1 100644 --- a/llvm/include/llvm/Analysis/CFG.h +++ b/llvm/include/llvm/Analysis/CFG.h @@ -96,6 +96,18 @@ bool isPotentiallyReachableFromMany( const SmallPtrSetImpl *ExclusionSet, const DominatorTree *DT = nullptr, const LoopInfo *LI = nullptr); +/// Determine whether there is a potentially a path from at least one block in +/// 'Worklist' to at least one block in 'StopSet' within a single function +/// without passing through any of the blocks in 'ExclusionSet'. Returns false +/// only if we can prove that once any block in 'Worklist' has been reached then +/// no blocks in 'StopSet' can be executed without passing through any blocks in +/// 'ExclusionSet'. Conservatively returns true. +bool isManyPotentiallyReachableFromMany( + SmallVectorImpl &Worklist, + const SmallPtrSetImpl &StopSet, + const SmallPtrSetImpl *ExclusionSet, + const DominatorTree *DT = nullptr, const LoopInfo *LI = nullptr); + /// Return true if the control flow in \p RPOTraversal is irreducible. /// /// This is a generic implementation to detect CFG irreducibility based on loop diff --git a/llvm/lib/Analysis/CFG.cpp b/llvm/lib/Analysis/CFG.cpp index 8528aa9f77e0..841b83505238 100644 --- a/llvm/lib/Analysis/CFG.cpp +++ b/llvm/lib/Analysis/CFG.cpp @@ -130,14 +130,21 @@ static const Loop *getOutermostLoop(const LoopInfo *LI, const BasicBlock *BB) { return L ? L->getOutermostLoop() : nullptr; } -bool llvm::isPotentiallyReachableFromMany( - SmallVectorImpl &Worklist, const BasicBlock *StopBB, - const SmallPtrSetImpl *ExclusionSet, const DominatorTree *DT, - const LoopInfo *LI) { - // When the stop block is unreachable, it's dominated from everywhere, +template +static bool isReachableImpl(SmallVectorImpl &Worklist, + const StopSetT &StopSet, + const SmallPtrSetImpl *ExclusionSet, + const DominatorTree *DT, const LoopInfo *LI) { + // When a stop block is unreachable, it's dominated from everywhere, // regardless of whether there's a path between the two blocks. - if (DT && !DT->isReachableFromEntry(StopBB)) - DT = nullptr; + if (DT) { + for (auto *BB : StopSet) { + if (!DT->isReachableFromEntry(BB)) { + DT = nullptr; + break; + } + } + } // We can't skip directly from a block that dominates the stop block if the // exclusion block is potentially in between. @@ -155,7 +162,13 @@ bool llvm::isPotentiallyReachableFromMany( } } - const Loop *StopLoop = LI ? getOutermostLoop(LI, StopBB) : nullptr; + SmallPtrSet StopLoops; + if (LI) { + for (auto *StopSetBB : StopSet) { + if (const Loop *L = getOutermostLoop(LI, StopSetBB)) + StopLoops.insert(L); + } + } unsigned Limit = DefaultMaxBBsToExplore; SmallPtrSet Visited; @@ -163,12 +176,16 @@ bool llvm::isPotentiallyReachableFromMany( BasicBlock *BB = Worklist.pop_back_val(); if (!Visited.insert(BB).second) continue; - if (BB == StopBB) + if (StopSet.contains(BB)) return true; if (ExclusionSet && ExclusionSet->count(BB)) continue; - if (DT && DT->dominates(BB, StopBB)) - return true; + if (DT) { + if (llvm::any_of(StopSet, [&](const BasicBlock *StopBB) { + return DT->dominates(BB, StopBB); + })) + return true; + } const Loop *Outer = nullptr; if (LI) { @@ -179,7 +196,7 @@ bool llvm::isPotentiallyReachableFromMany( // excluded block. Clear Outer so we process BB's successors. if (LoopsWithHoles.count(Outer)) Outer = nullptr; - if (StopLoop && Outer == StopLoop) + if (StopLoops.contains(Outer)) return true; } @@ -204,6 +221,39 @@ bool llvm::isPotentiallyReachableFromMany( return false; } +template class SingleEntrySet { +public: + using const_iterator = const T *; + + SingleEntrySet(T Elem) : Elem(Elem) {} + + bool contains(T Other) const { return Elem == Other; } + + const_iterator begin() const { return &Elem; } + const_iterator end() const { return &Elem + 1; } + +private: + T Elem; +}; + +bool llvm::isPotentiallyReachableFromMany( + SmallVectorImpl &Worklist, const BasicBlock *StopBB, + const SmallPtrSetImpl *ExclusionSet, const DominatorTree *DT, + const LoopInfo *LI) { + return isReachableImpl>( + Worklist, SingleEntrySet(StopBB), ExclusionSet, DT, + LI); +} + +bool llvm::isManyPotentiallyReachableFromMany( + SmallVectorImpl &Worklist, + const SmallPtrSetImpl &StopSet, + const SmallPtrSetImpl *ExclusionSet, const DominatorTree *DT, + const LoopInfo *LI) { + return isReachableImpl>( + Worklist, StopSet, ExclusionSet, DT, LI); +} + bool llvm::isPotentiallyReachable( const BasicBlock *A, const BasicBlock *B, const SmallPtrSetImpl *ExclusionSet, const DominatorTree *DT, diff --git a/llvm/lib/Transforms/Coroutines/CoroFrame.cpp b/llvm/lib/Transforms/Coroutines/CoroFrame.cpp index 08a4522e3fac..dd9e77a855ef 100644 --- a/llvm/lib/Transforms/Coroutines/CoroFrame.cpp +++ b/llvm/lib/Transforms/Coroutines/CoroFrame.cpp @@ -19,6 +19,7 @@ #include "llvm/ADT/PostOrderIterator.h" #include "llvm/ADT/ScopeExit.h" #include "llvm/ADT/SmallString.h" +#include "llvm/Analysis/CFG.h" #include "llvm/Analysis/PtrUseVisitor.h" #include "llvm/Analysis/StackLifetime.h" #include "llvm/Config/llvm-config.h" @@ -1440,17 +1441,22 @@ namespace { struct AllocaUseVisitor : PtrUseVisitor { using Base = PtrUseVisitor; AllocaUseVisitor(const DataLayout &DL, const DominatorTree &DT, - const CoroBeginInst &CB, const SuspendCrossingInfo &Checker, + const coro::Shape &CoroShape, + const SuspendCrossingInfo &Checker, bool ShouldUseLifetimeStartInfo) - : PtrUseVisitor(DL), DT(DT), CoroBegin(CB), Checker(Checker), - ShouldUseLifetimeStartInfo(ShouldUseLifetimeStartInfo) {} + : PtrUseVisitor(DL), DT(DT), CoroShape(CoroShape), Checker(Checker), + ShouldUseLifetimeStartInfo(ShouldUseLifetimeStartInfo) { + for (AnyCoroSuspendInst *SuspendInst : CoroShape.CoroSuspends) + CoroSuspendBBs.insert(SuspendInst->getParent()); + } void visit(Instruction &I) { Users.insert(&I); Base::visit(I); // If the pointer is escaped prior to CoroBegin, we have to assume it would // be written into before CoroBegin as well. - if (PI.isEscaped() && !DT.dominates(&CoroBegin, PI.getEscapingInst())) { + if (PI.isEscaped() && + !DT.dominates(CoroShape.CoroBegin, PI.getEscapingInst())) { MayWriteBeforeCoroBegin = true; } } @@ -1553,10 +1559,19 @@ struct AllocaUseVisitor : PtrUseVisitor { // When we found the lifetime markers refers to a // subrange of the original alloca, ignore the lifetime // markers to avoid misleading the analysis. - if (II.getIntrinsicID() != Intrinsic::lifetime_start || !IsOffsetKnown || - !Offset.isZero()) + if (!IsOffsetKnown || !Offset.isZero()) + return Base::visitIntrinsicInst(II); + switch (II.getIntrinsicID()) { + default: return Base::visitIntrinsicInst(II); - LifetimeStarts.insert(&II); + case Intrinsic::lifetime_start: + LifetimeStarts.insert(&II); + LifetimeStartBBs.push_back(II.getParent()); + break; + case Intrinsic::lifetime_end: + LifetimeEndBBs.insert(II.getParent()); + break; + } } void visitCallBase(CallBase &CB) { @@ -1586,7 +1601,7 @@ struct AllocaUseVisitor : PtrUseVisitor { private: const DominatorTree &DT; - const CoroBeginInst &CoroBegin; + const coro::Shape &CoroShape; const SuspendCrossingInfo &Checker; // All alias to the original AllocaInst, created before CoroBegin and used // after CoroBegin. Each entry contains the instruction and the offset in the @@ -1594,6 +1609,9 @@ private: DenseMap> AliasOffetMap{}; SmallPtrSet Users{}; SmallPtrSet LifetimeStarts{}; + SmallVector LifetimeStartBBs{}; + SmallPtrSet LifetimeEndBBs{}; + SmallPtrSet CoroSuspendBBs{}; bool MayWriteBeforeCoroBegin{false}; bool ShouldUseLifetimeStartInfo{true}; @@ -1605,10 +1623,19 @@ private: // every basic block that uses the pointer to see if they cross suspension // points. The uses cover both direct uses as well as indirect uses. if (ShouldUseLifetimeStartInfo && !LifetimeStarts.empty()) { - for (auto *I : Users) - for (auto *S : LifetimeStarts) - if (Checker.isDefinitionAcrossSuspend(*S, I)) - return true; + // If there is no explicit lifetime.end, then assume the address can + // cross suspension points. + if (LifetimeEndBBs.empty()) + return true; + + // If there is a path from a lifetime.start to a suspend without a + // corresponding lifetime.end, then the alloca's lifetime persists + // beyond that suspension point and the alloca must go on the frame. + llvm::SmallVector Worklist(LifetimeStartBBs); + if (isManyPotentiallyReachableFromMany(Worklist, CoroSuspendBBs, + &LifetimeEndBBs, &DT)) + return true; + // Addresses are guaranteed to be identical after every lifetime.start so // we cannot use the local stack if the address escaped and there is a // suspend point between lifetime markers. This should also cover the @@ -1646,13 +1673,13 @@ private: } void handleMayWrite(const Instruction &I) { - if (!DT.dominates(&CoroBegin, &I)) + if (!DT.dominates(CoroShape.CoroBegin, &I)) MayWriteBeforeCoroBegin = true; } bool usedAfterCoroBegin(Instruction &I) { for (auto &U : I.uses()) - if (DT.dominates(&CoroBegin, U)) + if (DT.dominates(CoroShape.CoroBegin, U)) return true; return false; } @@ -1661,7 +1688,7 @@ private: // We track all aliases created prior to CoroBegin but used after. // These aliases may need to be recreated after CoroBegin if the alloca // need to live on the frame. - if (DT.dominates(&CoroBegin, &I) || !usedAfterCoroBegin(I)) + if (DT.dominates(CoroShape.CoroBegin, &I) || !usedAfterCoroBegin(I)) return; if (!IsOffsetKnown) { @@ -2830,8 +2857,7 @@ static void collectFrameAlloca(AllocaInst *AI, coro::Shape &Shape, bool ShouldUseLifetimeStartInfo = (Shape.ABI != coro::ABI::Async && Shape.ABI != coro::ABI::Retcon && Shape.ABI != coro::ABI::RetconOnce); - AllocaUseVisitor Visitor{AI->getModule()->getDataLayout(), DT, - *Shape.CoroBegin, Checker, + AllocaUseVisitor Visitor{AI->getModule()->getDataLayout(), DT, Shape, Checker, ShouldUseLifetimeStartInfo}; Visitor.visitPtr(*AI); if (!Visitor.getShouldLiveOnFrame()) diff --git a/llvm/test/Transforms/Coroutines/coro-lifetime-end.ll b/llvm/test/Transforms/Coroutines/coro-lifetime-end.ll new file mode 100644 index 000000000000..330c61360e20 --- /dev/null +++ b/llvm/test/Transforms/Coroutines/coro-lifetime-end.ll @@ -0,0 +1,142 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 4 +; RUN: opt < %s -passes='cgscc(coro-split),simplifycfg,early-cse' -S | FileCheck %s + +declare ptr @malloc(i64) + +%i8.array = type { [100 x i8] } +declare void @consume.i8.array(ptr) + +@testbool = external local_unnamed_addr global i8, align 1 + +; testval does not contain an explicit lifetime end. We must assume that it may +; live across suspension. +define void @HasNoLifetimeEnd() presplitcoroutine { +; CHECK-LABEL: define void @HasNoLifetimeEnd() { +; CHECK-NEXT: entry: +; CHECK-NEXT: [[ID:%.*]] = call token @llvm.coro.id(i32 0, ptr null, ptr null, ptr @HasNoLifetimeEnd.resumers) +; CHECK-NEXT: [[ALLOC:%.*]] = call ptr @malloc(i64 16) +; CHECK-NEXT: [[VFRAME:%.*]] = call noalias nonnull ptr @llvm.coro.begin(token [[ID]], ptr [[ALLOC]]) +; CHECK-NEXT: store ptr @HasNoLifetimeEnd.resume, ptr [[VFRAME]], align 8 +; CHECK-NEXT: [[DESTROY_ADDR:%.*]] = getelementptr inbounds [[HASNOLIFETIMEEND_FRAME:%.*]], ptr [[VFRAME]], i32 0, i32 1 +; CHECK-NEXT: store ptr @HasNoLifetimeEnd.destroy, ptr [[DESTROY_ADDR]], align 8 +; CHECK-NEXT: [[INDEX_ADDR1:%.*]] = getelementptr inbounds [[HASNOLIFETIMEEND_FRAME]], ptr [[VFRAME]], i32 0, i32 2 +; CHECK-NEXT: call void @consume.i8.array(ptr [[INDEX_ADDR1]]) +; CHECK-NEXT: [[INDEX_ADDR2:%.*]] = getelementptr inbounds [[HASNOLIFETIMEEND_FRAME]], ptr [[VFRAME]], i32 0, i32 3 +; CHECK-NEXT: store i1 false, ptr [[INDEX_ADDR2]], align 1 +; CHECK-NEXT: ret void +; +entry: + %testval = alloca %i8.array + %id = call token @llvm.coro.id(i32 0, ptr null, ptr null, ptr null) + %alloc = call ptr @malloc(i64 16) #3 + %vFrame = call noalias nonnull ptr @llvm.coro.begin(token %id, ptr %alloc) + + call void @llvm.lifetime.start.p0(i64 100, ptr %testval) + call void @consume.i8.array(ptr %testval) + + %save = call token @llvm.coro.save(ptr null) + %suspend = call i8 @llvm.coro.suspend(token %save, i1 false) + switch i8 %suspend, label %exit [ + i8 0, label %await.ready + i8 1, label %exit + ] +await.ready: + br label %exit +exit: + call i1 @llvm.coro.end(ptr null, i1 false, token none) + ret void +} + +define void @LifetimeEndAfterCoroEnd() presplitcoroutine { +; CHECK-LABEL: define void @LifetimeEndAfterCoroEnd() { +; CHECK-NEXT: entry: +; CHECK-NEXT: [[ID:%.*]] = call token @llvm.coro.id(i32 0, ptr null, ptr null, ptr @LifetimeEndAfterCoroEnd.resumers) +; CHECK-NEXT: [[ALLOC:%.*]] = call ptr @malloc(i64 16) +; CHECK-NEXT: [[VFRAME:%.*]] = call noalias nonnull ptr @llvm.coro.begin(token [[ID]], ptr [[ALLOC]]) +; CHECK-NEXT: store ptr @LifetimeEndAfterCoroEnd.resume, ptr [[VFRAME]], align 8 +; CHECK-NEXT: [[DESTROY_ADDR:%.*]] = getelementptr inbounds [[LIFETIMEENDAFTERCOROEND_FRAME:%.*]], ptr [[VFRAME]], i32 0, i32 1 +; CHECK-NEXT: store ptr @LifetimeEndAfterCoroEnd.destroy, ptr [[DESTROY_ADDR]], align 8 +; CHECK-NEXT: [[INDEX_ADDR1:%.*]] = getelementptr inbounds [[LIFETIMEENDAFTERCOROEND_FRAME]], ptr [[VFRAME]], i32 0, i32 2 +; CHECK-NEXT: call void @consume.i8.array(ptr [[INDEX_ADDR1]]) +; CHECK-NEXT: [[INDEX_ADDR2:%.*]] = getelementptr inbounds [[LIFETIMEENDAFTERCOROEND_FRAME]], ptr [[VFRAME]], i32 0, i32 3 +; CHECK-NEXT: store i1 false, ptr [[INDEX_ADDR2]], align 1 +; CHECK-NEXT: ret void +; +entry: + %testval = alloca %i8.array + %id = call token @llvm.coro.id(i32 0, ptr null, ptr null, ptr null) + %alloc = call ptr @malloc(i64 16) #3 + %vFrame = call noalias nonnull ptr @llvm.coro.begin(token %id, ptr %alloc) + + call void @llvm.lifetime.start.p0(i64 100, ptr %testval) + call void @consume.i8.array(ptr %testval) + + %save = call token @llvm.coro.save(ptr null) + %suspend = call i8 @llvm.coro.suspend(token %save, i1 false) + switch i8 %suspend, label %exit [ + i8 0, label %await.ready + i8 1, label %exit + ] +await.ready: + br label %exit +exit: + call i1 @llvm.coro.end(ptr null, i1 false, token none) + call void @llvm.lifetime.end.p0(i64 100, ptr %testval) + ret void +} + +define void @BranchWithoutLifetimeEnd() presplitcoroutine { +; CHECK-LABEL: define void @BranchWithoutLifetimeEnd() { +; CHECK-NEXT: entry: +; CHECK-NEXT: [[ID:%.*]] = call token @llvm.coro.id(i32 0, ptr null, ptr null, ptr @BranchWithoutLifetimeEnd.resumers) +; CHECK-NEXT: [[ALLOC:%.*]] = call ptr @malloc(i64 16) +; CHECK-NEXT: [[VFRAME:%.*]] = call noalias nonnull ptr @llvm.coro.begin(token [[ID]], ptr [[ALLOC]]) +; CHECK-NEXT: store ptr @BranchWithoutLifetimeEnd.resume, ptr [[VFRAME]], align 8 +; CHECK-NEXT: [[DESTROY_ADDR:%.*]] = getelementptr inbounds [[BRANCHWITHOUTLIFETIMEEND_FRAME:%.*]], ptr [[VFRAME]], i32 0, i32 1 +; CHECK-NEXT: store ptr @BranchWithoutLifetimeEnd.destroy, ptr [[DESTROY_ADDR]], align 8 +; CHECK-NEXT: [[TESTVAL:%.*]] = getelementptr inbounds [[BRANCHWITHOUTLIFETIMEEND_FRAME]], ptr [[VFRAME]], i32 0, i32 2 +; CHECK-NEXT: call void @consume.i8.array(ptr [[TESTVAL]]) +; CHECK-NEXT: [[TMP0:%.*]] = load i8, ptr @testbool, align 1 +; CHECK-NEXT: [[INDEX_ADDR1:%.*]] = getelementptr inbounds [[BRANCHWITHOUTLIFETIMEEND_FRAME]], ptr [[VFRAME]], i32 0, i32 3 +; CHECK-NEXT: store i1 false, ptr [[INDEX_ADDR1]], align 1 +; CHECK-NEXT: ret void +; +entry: + %testval = alloca %i8.array + %id = call token @llvm.coro.id(i32 0, ptr null, ptr null, ptr null) + %alloc = call ptr @malloc(i64 16) #3 + %vFrame = call noalias nonnull ptr @llvm.coro.begin(token %id, ptr %alloc) + + call void @llvm.lifetime.start.p0(i64 100, ptr %testval) + call void @consume.i8.array(ptr %testval) + + %0 = load i8, ptr @testbool, align 1 + %tobool = trunc nuw i8 %0 to i1 + br i1 %tobool, label %if.then, label %if.end + +if.then: + call void @llvm.lifetime.end.p0(i64 100, ptr %testval) + br label %if.end + +if.end: + %save = call token @llvm.coro.save(ptr null) + %suspend = call i8 @llvm.coro.suspend(token %save, i1 false) + switch i8 %suspend, label %exit [ + i8 0, label %await.ready + i8 1, label %exit + ] +await.ready: + br label %exit +exit: + call i1 @llvm.coro.end(ptr null, i1 false, token none) + ret void +} + + +declare token @llvm.coro.id(i32, ptr readnone, ptr nocapture readonly, ptr) +declare ptr @llvm.coro.begin(token, ptr writeonly) #3 +declare ptr @llvm.coro.frame() #5 +declare i8 @llvm.coro.suspend(token, i1) #3 +declare i1 @llvm.coro.end(ptr, i1, token) #3 +declare void @llvm.lifetime.start.p0(i64, ptr nocapture) #4 +declare void @llvm.lifetime.end.p0(i64, ptr nocapture) #4 -- GitLab From 557bf3835b96ef5839013b1e821a1cb869660aa3 Mon Sep 17 00:00:00 2001 From: Yingwei Zheng Date: Wed, 22 May 2024 00:48:26 +0800 Subject: [PATCH 009/452] [RISCV][ISel] Allow opaque constants in `hasAndNotCompare` (#92926) See the following code: https://github.com/llvm/llvm-project/blob/4ae896fe979b7db501cabde4b6b3504478958682/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp#L9334-L9357 > Combining: t47: i64 = xor t43, OpaqueConstant:i64<31808> X: i64 = Constant<0> Y: i64 = OpaqueConstant<31808> The assertion failed because both `X` and `Y` are constants. This patch allows opaque constants in `hasAndNotCompare` to fix the issue. Fixes https://github.com/llvm/llvm-project/issues/90730. --- llvm/lib/Target/RISCV/RISCVISelLowering.cpp | 2 +- llvm/test/CodeGen/RISCV/pr90730.ll | 22 +++++++++++++++++++++ 2 files changed, 23 insertions(+), 1 deletion(-) create mode 100644 llvm/test/CodeGen/RISCV/pr90730.ll diff --git a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp index 06f85698d296..05859a1f4898 100644 --- a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp +++ b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp @@ -1919,7 +1919,7 @@ bool RISCVTargetLowering::hasAndNotCompare(SDValue Y) const { return false; return (Subtarget.hasStdExtZbb() || Subtarget.hasStdExtZbkb()) && - !isa(Y); + (!isa(Y) || cast(Y)->isOpaque()); } bool RISCVTargetLowering::hasBitTest(SDValue X, SDValue Y) const { diff --git a/llvm/test/CodeGen/RISCV/pr90730.ll b/llvm/test/CodeGen/RISCV/pr90730.ll new file mode 100644 index 000000000000..7c3f4b43089c --- /dev/null +++ b/llvm/test/CodeGen/RISCV/pr90730.ll @@ -0,0 +1,22 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 4 +; RUN: llc < %s -mtriple=riscv64 -mattr=+zbb | FileCheck %s + +define i32 @pr90730(i32 %x, i1 %y, ptr %p) { +; CHECK-LABEL: pr90730: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: lui a1, 8 +; CHECK-NEXT: addiw a1, a1, -960 +; CHECK-NEXT: andn a0, a1, a0 +; CHECK-NEXT: sw zero, 0(a2) +; CHECK-NEXT: ret +entry: + %ext = zext i1 %y to i32 + %xor1 = xor i32 %ext, 31817 + %and1 = and i32 %xor1, %x + store i32 %and1, ptr %p, align 4 + %v = load i32, ptr %p, align 4 + %and2 = and i32 %v, 31808 + %xor2 = xor i32 %and2, 31808 + store i32 0, ptr %p, align 4 + ret i32 %xor2 +} -- GitLab From 4636b66de513dfa15da1ba071f279b64ad68903f Mon Sep 17 00:00:00 2001 From: Felix Schneider Date: Tue, 21 May 2024 18:52:48 +0200 Subject: [PATCH 010/452] [mlir][intrange] Represent bounds of `ReflectBoundsOp` as `si`/`ui` (#92641) This patch adapts the `test.reflect_bounds` test Op to use explicitly signed and unsigned representation for signed and unsigned bounds of `IntegerType`s. This is mostly a cosmetic change as the internal representation of the ranges is unchanged. However, it improves readability of tests. --- .../Dialect/Arith/int-range-interface.mlir | 2 +- mlir/test/Dialect/Arith/int-range-opts.mlir | 4 ++-- mlir/test/lib/Dialect/Test/TestOpDefs.cpp | 19 ++++++++++++++----- 3 files changed, 17 insertions(+), 8 deletions(-) diff --git a/mlir/test/Dialect/Arith/int-range-interface.mlir b/mlir/test/Dialect/Arith/int-range-interface.mlir index 16524b363472..17d3fcfc13ce 100644 --- a/mlir/test/Dialect/Arith/int-range-interface.mlir +++ b/mlir/test/Dialect/Arith/int-range-interface.mlir @@ -758,7 +758,7 @@ func.func private @callee(%arg0: memref) { } // CHECK-LABEL: func @test_i8_bounds -// CHECK: test.reflect_bounds {smax = 127 : i8, smin = -128 : i8, umax = -1 : i8, umin = 0 : i8} +// CHECK: test.reflect_bounds {smax = 127 : si8, smin = -128 : si8, umax = 255 : ui8, umin = 0 : ui8} func.func @test_i8_bounds() -> i8 { %cst1 = arith.constant 1 : i8 %0 = test.with_bounds { umin = 0 : i8, umax = 255 : i8, smin = -128 : i8, smax = 127 : i8 } : i8 diff --git a/mlir/test/Dialect/Arith/int-range-opts.mlir b/mlir/test/Dialect/Arith/int-range-opts.mlir index 6179003ab4e7..71174f1c5ef0 100644 --- a/mlir/test/Dialect/Arith/int-range-opts.mlir +++ b/mlir/test/Dialect/Arith/int-range-opts.mlir @@ -75,7 +75,7 @@ func.func @test() -> i1 { // ----- // CHECK-LABEL: func @test -// CHECK: test.reflect_bounds {smax = 24 : i8, smin = 0 : i8, umax = 24 : i8, umin = 0 : i8} +// CHECK: test.reflect_bounds {smax = 24 : si8, smin = 0 : si8, umax = 24 : ui8, umin = 0 : ui8} func.func @test() -> i8 { %cst1 = arith.constant 1 : i8 %i8val = test.with_bounds { umin = 0 : i8, umax = 12 : i8, smin = 0 : i8, smax = 12 : i8 } : i8 @@ -87,7 +87,7 @@ func.func @test() -> i8 { // ----- // CHECK-LABEL: func @test -// CHECK: test.reflect_bounds {smax = 127 : i8, smin = -128 : i8, umax = -1 : i8, umin = 0 : i8} +// CHECK: test.reflect_bounds {smax = 127 : si8, smin = -128 : si8, umax = 255 : ui8, umin = 0 : ui8} func.func @test() -> i8 { %cst1 = arith.constant 1 : i8 %i8val = test.with_bounds { umin = 0 : i8, umax = 127 : i8, smin = 0 : i8, smax = 127 : i8 } : i8 diff --git a/mlir/test/lib/Dialect/Test/TestOpDefs.cpp b/mlir/test/lib/Dialect/Test/TestOpDefs.cpp index bfee0391f670..b058a8e1abbc 100644 --- a/mlir/test/lib/Dialect/Test/TestOpDefs.cpp +++ b/mlir/test/lib/Dialect/Test/TestOpDefs.cpp @@ -706,11 +706,20 @@ void TestReflectBoundsOp::inferResultRanges( const ConstantIntRanges &range = argRanges[0]; MLIRContext *ctx = getContext(); Builder b(ctx); - auto intTy = getType(); - setUminAttr(b.getIntegerAttr(intTy, range.umin())); - setUmaxAttr(b.getIntegerAttr(intTy, range.umax())); - setSminAttr(b.getIntegerAttr(intTy, range.smin())); - setSmaxAttr(b.getIntegerAttr(intTy, range.smax())); + Type sIntTy, uIntTy; + // For plain `IntegerType`s, we can derive the appropriate signed and unsigned + // Types for the Attributes. + if (auto intTy = llvm::dyn_cast(getType())) { + unsigned bitwidth = intTy.getWidth(); + sIntTy = b.getIntegerType(bitwidth, /*isSigned=*/true); + uIntTy = b.getIntegerType(bitwidth, /*isSigned=*/false); + } else + sIntTy = uIntTy = getType(); + + setUminAttr(b.getIntegerAttr(uIntTy, range.umin())); + setUmaxAttr(b.getIntegerAttr(uIntTy, range.umax())); + setSminAttr(b.getIntegerAttr(sIntTy, range.smin())); + setSmaxAttr(b.getIntegerAttr(sIntTy, range.smax())); setResultRanges(getResult(), range); } -- GitLab From 0eca2655843e1b79e6c65c7239bce8c9a1509568 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Valentin=20Clement=20=28=E3=83=90=E3=83=AC=E3=83=B3?= =?UTF-8?q?=E3=82=BF=E3=82=A4=E3=83=B3=20=E3=82=AF=E3=83=AC=E3=83=A1?= =?UTF-8?q?=E3=83=B3=29?= Date: Tue, 21 May 2024 09:59:35 -0700 Subject: [PATCH 011/452] [flang][cuda] Fix memory side effects on cuf.data_transfer op (#92928) The memory side effects on the `cuf.data_transfer` operation were swapped between the src and dst operands. We read from source and write to destination not the opposite. --- flang/include/flang/Optimizer/Dialect/CUF/CUFOps.td | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/flang/include/flang/Optimizer/Dialect/CUF/CUFOps.td b/flang/include/flang/Optimizer/Dialect/CUF/CUFOps.td index 72157bce4f76..1c98b4131a13 100644 --- a/flang/include/flang/Optimizer/Dialect/CUF/CUFOps.td +++ b/flang/include/flang/Optimizer/Dialect/CUF/CUFOps.td @@ -154,8 +154,8 @@ def cuf_DataTransferOp : cuf_Op<"data_transfer", []> { ``` }]; - let arguments = (ins Arg:$src, - Arg:$dst, + let arguments = (ins Arg:$src, + Arg:$dst, cuf_DataTransferKindAttr:$transfer_kind); let assemblyFormat = [{ -- GitLab From 3e15c97fa3812993bdc319827a5c6d867b765ae8 Mon Sep 17 00:00:00 2001 From: "A. Jiang" Date: Wed, 22 May 2024 01:05:51 +0800 Subject: [PATCH 012/452] [libc++] LWG2381: Inconsistency in parsing floating point numbers (#77948) This PR implements [LWG2381](https://cplusplus.github.io/LWG/issue2381) by rejecting `'i'`, `'I'`, `'n'`, `'N'` in FP parsing, as inf and NaN are intendedly rejected by that LWG issue. The source character array used for parsing is `"0123456789abcdefABCDEFxX+-pPiInN"`, whose first 26 or 28 characters are used for parsing integers or floating-point values respectively. Previously, libc++ used 32 characters, including `'i'`, `'I'`, `'n'`, `'N'`, for FP parsing, which was inconsistent with LWG2381. This PR also replaces magic numbers 26 and 28 (formerly 32) with named constants. Drive-by change: when the first character (possibly after the leading `'+'` or `'-'`) is not a decimal digit but an acceptable character (e.g., `'p'` or `'e'`), the character is not accumulated now (per Stage 2 in [facet.num.get.virtuals]/3). #65168 may be rendered invalid, see https://github.com/llvm/llvm-project/pull/65168#issuecomment-1868533342. Apple back-deployment targets remain broken, likely due to dylib. XFAIL is marked in related tests. --------- Co-authored-by: Mark de Wever --- libcxx/docs/Status/Cxx23Issues.csv | 2 +- libcxx/include/locale | 53 ++++-- .../facet.num.get.members/get_double.pass.cpp | 161 ++++++++++++++++-- .../facet.num.get.members/get_float.pass.cpp | 161 ++++++++++++++++-- .../get_long_double.pass.cpp | 161 ++++++++++++++++-- 5 files changed, 467 insertions(+), 71 deletions(-) diff --git a/libcxx/docs/Status/Cxx23Issues.csv b/libcxx/docs/Status/Cxx23Issues.csv index d421feef8db9..cc601b3cd3c9 100644 --- a/libcxx/docs/Status/Cxx23Issues.csv +++ b/libcxx/docs/Status/Cxx23Issues.csv @@ -98,7 +98,7 @@ `3555 `__,"``{transform,elements}_view::iterator::iterator_concept`` should consider const-qualification of the underlying range","June 2021","","","|ranges|" "","","","","","" `2191 `__,"Incorrect specification of ``match_results(match_results&&)``","October 2021","|Nothing To Do|","" -`2381 `__,"Inconsistency in parsing floating point numbers","October 2021","","" +`2381 `__,"Inconsistency in parsing floating point numbers","October 2021","|Complete|","19.0" `2762 `__,"``unique_ptr operator*()`` should be ``noexcept``","October 2021","","" `3121 `__,"``tuple`` constructor constraints for ``UTypes&&...`` overloads","October 2021","","" `3123 `__,"``duration`` constructor from representation shouldn't be effectively non-throwing","October 2021","","","|chrono|" diff --git a/libcxx/include/locale b/libcxx/include/locale index 748b276a8525..041d7bcd27fc 100644 --- a/libcxx/include/locale +++ b/libcxx/include/locale @@ -368,7 +368,11 @@ struct _LIBCPP_EXPORTED_FROM_ABI __num_get_base { static const int __num_get_buf_sz = 40; static int __get_base(ios_base&); - static const char __src[33]; + static const char __src[33]; // "0123456789abcdefABCDEFxX+-pPiInN" + // count of leading characters in __src used for parsing integers ("012..X+-") + static const size_t __int_chr_cnt = 26; + // count of leading characters in __src used for parsing floating-point values ("012..-pP") + static const size_t __fp_chr_cnt = 28; }; _LIBCPP_EXPORTED_FROM_ABI void @@ -431,7 +435,7 @@ private: template const _Tp* __do_widen_p(ios_base& __iob, _Tp* __atoms) const { locale __loc = __iob.getloc(); - use_facet >(__loc).widen(__src, __src + 26, __atoms); + use_facet >(__loc).widen(__src, __src + __int_chr_cnt, __atoms); return __atoms; } @@ -447,7 +451,7 @@ private: template string __num_get<_CharT>::__stage2_int_prep(ios_base& __iob, _CharT* __atoms, _CharT& __thousands_sep) { locale __loc = __iob.getloc(); - std::use_facet >(__loc).widen(__src, __src + 26, __atoms); + std::use_facet >(__loc).widen(__src, __src + __int_chr_cnt, __atoms); const numpunct<_CharT>& __np = std::use_facet >(__loc); __thousands_sep = __np.thousands_sep(); return __np.grouping(); @@ -458,7 +462,7 @@ template string __num_get<_CharT>::__stage2_float_prep( ios_base& __iob, _CharT* __atoms, _CharT& __decimal_point, _CharT& __thousands_sep) { locale __loc = __iob.getloc(); - std::use_facet >(__loc).widen(__src, __src + 32, __atoms); + std::use_facet >(__loc).widen(__src, __src + __fp_chr_cnt, __atoms); const numpunct<_CharT>& __np = std::use_facet >(__loc); __decimal_point = __np.decimal_point(); __thousands_sep = __np.thousands_sep(); @@ -490,7 +494,7 @@ __num_get<_CharT>::__stage2_int_loop(_CharT __ct, int __base, char* __a, char*& } return 0; } - ptrdiff_t __f = std::find(__atoms, __atoms + 26, __ct) - __atoms; + ptrdiff_t __f = std::find(__atoms, __atoms + __int_chr_cnt, __ct) - __atoms; if (__f >= 24) return -1; switch (__base) { @@ -546,8 +550,8 @@ int __num_get<_CharT>::__stage2_float_loop( } return 0; } - ptrdiff_t __f = std::find(__atoms, __atoms + 32, __ct) - __atoms; - if (__f >= 32) + ptrdiff_t __f = std::find(__atoms, __atoms + __num_get_base::__fp_chr_cnt, __ct) - __atoms; + if (__f >= static_cast(__num_get_base::__fp_chr_cnt)) return -1; char __x = __src[__f]; if (__x == '-' || __x == '+') { @@ -846,7 +850,7 @@ _InputIterator num_get<_CharT, _InputIterator>::__do_get_signed( int __base = this->__get_base(__iob); // Stage 2 char_type __thousands_sep; - const int __atoms_size = 26; + const int __atoms_size = __num_get_base::__int_chr_cnt; #ifdef _LIBCPP_ABI_OPTIMIZED_LOCALE_NUM_GET char_type __atoms1[__atoms_size]; const char_type* __atoms = this->__do_widen(__iob, __atoms1); @@ -895,7 +899,7 @@ _InputIterator num_get<_CharT, _InputIterator>::__do_get_unsigned( int __base = this->__get_base(__iob); // Stage 2 char_type __thousands_sep; - const int __atoms_size = 26; + const int __atoms_size = __num_get_base::__int_chr_cnt; #ifdef _LIBCPP_ABI_OPTIMIZED_LOCALE_NUM_GET char_type __atoms1[__atoms_size]; const char_type* __atoms = this->__do_widen(__iob, __atoms1); @@ -942,7 +946,7 @@ _InputIterator num_get<_CharT, _InputIterator>::__do_get_floating_point( iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, _Fp& __v) const { // Stage 1, nothing to do // Stage 2 - char_type __atoms[32]; + char_type __atoms[__num_get_base::__fp_chr_cnt]; char_type __decimal_point; char_type __thousands_sep; string __grouping = this->__stage2_float_prep(__iob, __atoms, __decimal_point, __thousands_sep); @@ -951,10 +955,11 @@ _InputIterator num_get<_CharT, _InputIterator>::__do_get_floating_point( char* __a = &__buf[0]; char* __a_end = __a; unsigned __g[__num_get_base::__num_get_buf_sz]; - unsigned* __g_end = __g; - unsigned __dc = 0; - bool __in_units = true; - char __exp = 'E'; + unsigned* __g_end = __g; + unsigned __dc = 0; + bool __in_units = true; + char __exp = 'E'; + bool __is_leading_parsed = false; for (; __b != __e; ++__b) { if (__a_end == __a + __buf.size()) { size_t __tmp = __buf.size(); @@ -977,6 +982,21 @@ _InputIterator num_get<_CharT, _InputIterator>::__do_get_floating_point( __dc, __atoms)) break; + + // the leading character excluding the sign must be a decimal digit + if (!__is_leading_parsed) { + if (__a_end - __a >= 1 && __a[0] != '-' && __a[0] != '+') { + if ('0' <= __a[0] && __a[0] <= '9') + __is_leading_parsed = true; + else + break; + } else if (__a_end - __a >= 2 && (__a[0] == '-' || __a[0] == '+')) { + if ('0' <= __a[1] && __a[1] <= '9') + __is_leading_parsed = true; + else + break; + } + } } if (__grouping.size() != 0 && __in_units && __g_end - __g < __num_get_base::__num_get_buf_sz) *__g_end++ = __dc; @@ -996,10 +1016,11 @@ _InputIterator num_get<_CharT, _InputIterator>::do_get( // Stage 1 int __base = 16; // Stage 2 - char_type __atoms[26]; + char_type __atoms[__num_get_base::__int_chr_cnt]; char_type __thousands_sep = char_type(); string __grouping; - std::use_facet >(__iob.getloc()).widen(__num_get_base::__src, __num_get_base::__src + 26, __atoms); + std::use_facet >(__iob.getloc()) + .widen(__num_get_base::__src, __num_get_base::__src + __num_get_base::__int_chr_cnt, __atoms); string __buf; __buf.resize(__buf.capacity()); char* __a = &__buf[0]; diff --git a/libcxx/test/std/localization/locale.categories/category.numeric/locale.num.get/facet.num.get.members/get_double.pass.cpp b/libcxx/test/std/localization/locale.categories/category.numeric/locale.num.get/facet.num.get.members/get_double.pass.cpp index c802ab787682..fbd1c7c5715e 100644 --- a/libcxx/test/std/localization/locale.categories/category.numeric/locale.num.get/facet.num.get.members/get_double.pass.cpp +++ b/libcxx/test/std/localization/locale.categories/category.numeric/locale.num.get/facet.num.get.members/get_double.pass.cpp @@ -6,6 +6,11 @@ // //===----------------------------------------------------------------------===// +// The fix for LWG2381 (https://github.com/llvm/llvm-project/pull/77948) changed +// behavior of FP parsing, while Apple back-deployment targets remain broken due +// to the dylib. +// UNSUPPORTED: using-built-library-before-llvm-19 + // // class num_get @@ -116,9 +121,9 @@ int main(int, char**) f.get(cpp17_input_iterator(str), cpp17_input_iterator(str+sizeof(str)), ios, err, v); - assert(base(iter) == str+sizeof(str)-1); - assert(err == ios.goodbit); - assert(v == INFINITY); + assert(base(iter) == str); + assert(err == ios.failbit); + assert(v == 0.0); } { const char str[] = "INF"; @@ -128,9 +133,9 @@ int main(int, char**) f.get(cpp17_input_iterator(str), cpp17_input_iterator(str+sizeof(str)), ios, err, v); - assert(base(iter) == str+sizeof(str)-1); - assert(err == ios.goodbit); - assert(v == INFINITY); + assert(base(iter) == str); + assert(err == ios.failbit); + assert(v == 0.0); } { const char str[] = "-inf"; @@ -140,9 +145,9 @@ int main(int, char**) f.get(cpp17_input_iterator(str), cpp17_input_iterator(str+sizeof(str)), ios, err, v); - assert(base(iter) == str+sizeof(str)-1); - assert(err == ios.goodbit); - assert(v == -INFINITY); + assert(base(iter) == str + 1); + assert(err == ios.failbit); + assert(v == 0.0); } { const char str[] = "-INF"; @@ -152,9 +157,9 @@ int main(int, char**) f.get(cpp17_input_iterator(str), cpp17_input_iterator(str+sizeof(str)), ios, err, v); - assert(base(iter) == str+sizeof(str)-1); - assert(err == ios.goodbit); - assert(v == -INFINITY); + assert(base(iter) == str + 1); + assert(err == ios.failbit); + assert(v == 0.0); } { const char str[] = "nan"; @@ -164,9 +169,9 @@ int main(int, char**) f.get(cpp17_input_iterator(str), cpp17_input_iterator(str+sizeof(str)), ios, err, v); - assert(base(iter) == str+sizeof(str)-1); - assert(err == ios.goodbit); - assert(std::isnan(v)); + assert(base(iter) == str); + assert(err == ios.failbit); + assert(v == 0.0); } { const char str[] = "NAN"; @@ -176,9 +181,129 @@ int main(int, char**) f.get(cpp17_input_iterator(str), cpp17_input_iterator(str+sizeof(str)), ios, err, v); - assert(base(iter) == str+sizeof(str)-1); - assert(err == ios.goodbit); - assert(std::isnan(v)); + assert(base(iter) == str); + assert(err == ios.failbit); + assert(v == 0.0); + } + { + const char str[] = "p00"; + std::hex(ios); + std::ios_base::iostate err = ios.goodbit; + cpp17_input_iterator iter = f.get( + cpp17_input_iterator(str), cpp17_input_iterator(str + sizeof(str)), ios, err, v); + assert(base(iter) == str); + assert(err == ios.failbit); + assert(v == 0.0); + } + { + const char str[] = "P00"; + std::hex(ios); + std::ios_base::iostate err = ios.goodbit; + cpp17_input_iterator iter = f.get( + cpp17_input_iterator(str), cpp17_input_iterator(str + sizeof(str)), ios, err, v); + assert(base(iter) == str); + assert(err == ios.failbit); + assert(v == 0.0); + } + { + const char str[] = "+p00"; + std::hex(ios); + std::ios_base::iostate err = ios.goodbit; + cpp17_input_iterator iter = f.get( + cpp17_input_iterator(str), cpp17_input_iterator(str + sizeof(str)), ios, err, v); + assert(base(iter) == str + 1); + assert(err == ios.failbit); + assert(v == 0.0); + } + { + const char str[] = "+P00"; + std::hex(ios); + std::ios_base::iostate err = ios.goodbit; + cpp17_input_iterator iter = f.get( + cpp17_input_iterator(str), cpp17_input_iterator(str + sizeof(str)), ios, err, v); + assert(base(iter) == str + 1); + assert(err == ios.failbit); + assert(v == 0.0); + } + { + const char str[] = "-p00"; + std::hex(ios); + std::ios_base::iostate err = ios.goodbit; + cpp17_input_iterator iter = f.get( + cpp17_input_iterator(str), cpp17_input_iterator(str + sizeof(str)), ios, err, v); + assert(base(iter) == str + 1); + assert(err == ios.failbit); + assert(v == 0.0); + } + { + const char str[] = "-P00"; + std::hex(ios); + std::ios_base::iostate err = ios.goodbit; + cpp17_input_iterator iter = f.get( + cpp17_input_iterator(str), cpp17_input_iterator(str + sizeof(str)), ios, err, v); + assert(base(iter) == str + 1); + assert(err == ios.failbit); + assert(v == 0.0); + } + { + const char str[] = "e00"; + std::hex(ios); + std::ios_base::iostate err = ios.goodbit; + cpp17_input_iterator iter = f.get( + cpp17_input_iterator(str), cpp17_input_iterator(str + sizeof(str)), ios, err, v); + assert(base(iter) == str); + assert(err == ios.failbit); + assert(v == 0.0); + } + { + const char str[] = "E00"; + std::hex(ios); + std::ios_base::iostate err = ios.goodbit; + cpp17_input_iterator iter = f.get( + cpp17_input_iterator(str), cpp17_input_iterator(str + sizeof(str)), ios, err, v); + assert(base(iter) == str); + assert(err == ios.failbit); + assert(v == 0.0); + } + { + const char str[] = "+e00"; + std::hex(ios); + std::ios_base::iostate err = ios.goodbit; + cpp17_input_iterator iter = f.get( + cpp17_input_iterator(str), cpp17_input_iterator(str + sizeof(str)), ios, err, v); + assert(base(iter) == str + 1); + assert(err == ios.failbit); + assert(v == 0.0); + } + { + const char str[] = "+E00"; + std::hex(ios); + std::ios_base::iostate err = ios.goodbit; + cpp17_input_iterator iter = f.get( + cpp17_input_iterator(str), cpp17_input_iterator(str + sizeof(str)), ios, err, v); + assert(base(iter) == str + 1); + assert(err == ios.failbit); + assert(v == 0.0); + } + { + const char str[] = "-e00"; + std::hex(ios); + std::ios_base::iostate err = ios.goodbit; + cpp17_input_iterator iter = f.get( + cpp17_input_iterator(str), cpp17_input_iterator(str + sizeof(str)), ios, err, v); + assert(base(iter) == str + 1); + assert(err == ios.failbit); + assert(v == 0.0); + } + { + const char str[] = "-E00"; + std::hex(ios); + std::ios_base::iostate err = ios.goodbit; + cpp17_input_iterator iter = f.get( + cpp17_input_iterator(str), cpp17_input_iterator(str + sizeof(str)), ios, err, v); + assert(base(iter) == str + 1); + assert(err == ios.failbit); + assert(v == 0.0); } { v = -1; diff --git a/libcxx/test/std/localization/locale.categories/category.numeric/locale.num.get/facet.num.get.members/get_float.pass.cpp b/libcxx/test/std/localization/locale.categories/category.numeric/locale.num.get/facet.num.get.members/get_float.pass.cpp index 79c8480d0699..b5ac7d876157 100644 --- a/libcxx/test/std/localization/locale.categories/category.numeric/locale.num.get/facet.num.get.members/get_float.pass.cpp +++ b/libcxx/test/std/localization/locale.categories/category.numeric/locale.num.get/facet.num.get.members/get_float.pass.cpp @@ -6,6 +6,11 @@ // //===----------------------------------------------------------------------===// +// The fix for LWG2381 (https://github.com/llvm/llvm-project/pull/77948) changed +// behavior of FP parsing, while Apple back-deployment targets remain broken due +// to the dylib. +// UNSUPPORTED: using-built-library-before-llvm-19 + // // class num_get @@ -105,9 +110,9 @@ int main(int, char**) f.get(cpp17_input_iterator(str), cpp17_input_iterator(str+sizeof(str)), ios, err, v); - assert(base(iter) == str+sizeof(str)-1); - assert(err == ios.goodbit); - assert(v == INFINITY); + assert(base(iter) == str); + assert(err == ios.failbit); + assert(v == 0.0f); } { const char str[] = "INF"; @@ -117,9 +122,9 @@ int main(int, char**) f.get(cpp17_input_iterator(str), cpp17_input_iterator(str+sizeof(str)), ios, err, v); - assert(base(iter) == str+sizeof(str)-1); - assert(err == ios.goodbit); - assert(v == INFINITY); + assert(base(iter) == str); + assert(err == ios.failbit); + assert(v == 0.0f); } { const char str[] = "-inf"; @@ -129,9 +134,9 @@ int main(int, char**) f.get(cpp17_input_iterator(str), cpp17_input_iterator(str+sizeof(str)), ios, err, v); - assert(base(iter) == str+sizeof(str)-1); - assert(err == ios.goodbit); - assert(v == -INFINITY); + assert(base(iter) == str + 1); + assert(err == ios.failbit); + assert(v == 0.0f); } { const char str[] = "-INF"; @@ -141,9 +146,9 @@ int main(int, char**) f.get(cpp17_input_iterator(str), cpp17_input_iterator(str+sizeof(str)), ios, err, v); - assert(base(iter) == str+sizeof(str)-1); - assert(err == ios.goodbit); - assert(v == -INFINITY); + assert(base(iter) == str + 1); + assert(err == ios.failbit); + assert(v == 0.0f); } { const char str[] = "nan"; @@ -153,9 +158,9 @@ int main(int, char**) f.get(cpp17_input_iterator(str), cpp17_input_iterator(str+sizeof(str)), ios, err, v); - assert(base(iter) == str+sizeof(str)-1); - assert(err == ios.goodbit); - assert(std::isnan(v)); + assert(base(iter) == str); + assert(err == ios.failbit); + assert(v == 0.0f); } { const char str[] = "NAN"; @@ -165,9 +170,129 @@ int main(int, char**) f.get(cpp17_input_iterator(str), cpp17_input_iterator(str+sizeof(str)), ios, err, v); - assert(base(iter) == str+sizeof(str)-1); - assert(err == ios.goodbit); - assert(std::isnan(v)); + assert(base(iter) == str); + assert(err == ios.failbit); + assert(v == 0.0f); + } + { + const char str[] = "p00"; + std::hex(ios); + std::ios_base::iostate err = ios.goodbit; + cpp17_input_iterator iter = f.get( + cpp17_input_iterator(str), cpp17_input_iterator(str + sizeof(str)), ios, err, v); + assert(base(iter) == str); + assert(err == ios.failbit); + assert(v == 0.0f); + } + { + const char str[] = "P00"; + std::hex(ios); + std::ios_base::iostate err = ios.goodbit; + cpp17_input_iterator iter = f.get( + cpp17_input_iterator(str), cpp17_input_iterator(str + sizeof(str)), ios, err, v); + assert(base(iter) == str); + assert(err == ios.failbit); + assert(v == 0.0f); + } + { + const char str[] = "+p00"; + std::hex(ios); + std::ios_base::iostate err = ios.goodbit; + cpp17_input_iterator iter = f.get( + cpp17_input_iterator(str), cpp17_input_iterator(str + sizeof(str)), ios, err, v); + assert(base(iter) == str + 1); + assert(err == ios.failbit); + assert(v == 0.0f); + } + { + const char str[] = "+P00"; + std::hex(ios); + std::ios_base::iostate err = ios.goodbit; + cpp17_input_iterator iter = f.get( + cpp17_input_iterator(str), cpp17_input_iterator(str + sizeof(str)), ios, err, v); + assert(base(iter) == str + 1); + assert(err == ios.failbit); + assert(v == 0.0f); + } + { + const char str[] = "-p00"; + std::hex(ios); + std::ios_base::iostate err = ios.goodbit; + cpp17_input_iterator iter = f.get( + cpp17_input_iterator(str), cpp17_input_iterator(str + sizeof(str)), ios, err, v); + assert(base(iter) == str + 1); + assert(err == ios.failbit); + assert(v == 0.0f); + } + { + const char str[] = "-P00"; + std::hex(ios); + std::ios_base::iostate err = ios.goodbit; + cpp17_input_iterator iter = f.get( + cpp17_input_iterator(str), cpp17_input_iterator(str + sizeof(str)), ios, err, v); + assert(base(iter) == str + 1); + assert(err == ios.failbit); + assert(v == 0.0f); + } + { + const char str[] = "e00"; + std::hex(ios); + std::ios_base::iostate err = ios.goodbit; + cpp17_input_iterator iter = f.get( + cpp17_input_iterator(str), cpp17_input_iterator(str + sizeof(str)), ios, err, v); + assert(base(iter) == str); + assert(err == ios.failbit); + assert(v == 0.0f); + } + { + const char str[] = "E00"; + std::hex(ios); + std::ios_base::iostate err = ios.goodbit; + cpp17_input_iterator iter = f.get( + cpp17_input_iterator(str), cpp17_input_iterator(str + sizeof(str)), ios, err, v); + assert(base(iter) == str); + assert(err == ios.failbit); + assert(v == 0.0f); + } + { + const char str[] = "+e00"; + std::hex(ios); + std::ios_base::iostate err = ios.goodbit; + cpp17_input_iterator iter = f.get( + cpp17_input_iterator(str), cpp17_input_iterator(str + sizeof(str)), ios, err, v); + assert(base(iter) == str + 1); + assert(err == ios.failbit); + assert(v == 0.0f); + } + { + const char str[] = "+E00"; + std::hex(ios); + std::ios_base::iostate err = ios.goodbit; + cpp17_input_iterator iter = f.get( + cpp17_input_iterator(str), cpp17_input_iterator(str + sizeof(str)), ios, err, v); + assert(base(iter) == str + 1); + assert(err == ios.failbit); + assert(v == 0.0f); + } + { + const char str[] = "-e00"; + std::hex(ios); + std::ios_base::iostate err = ios.goodbit; + cpp17_input_iterator iter = f.get( + cpp17_input_iterator(str), cpp17_input_iterator(str + sizeof(str)), ios, err, v); + assert(base(iter) == str + 1); + assert(err == ios.failbit); + assert(v == 0.0f); + } + { + const char str[] = "-E00"; + std::hex(ios); + std::ios_base::iostate err = ios.goodbit; + cpp17_input_iterator iter = f.get( + cpp17_input_iterator(str), cpp17_input_iterator(str + sizeof(str)), ios, err, v); + assert(base(iter) == str + 1); + assert(err == ios.failbit); + assert(v == 0.0f); } { v = -1; diff --git a/libcxx/test/std/localization/locale.categories/category.numeric/locale.num.get/facet.num.get.members/get_long_double.pass.cpp b/libcxx/test/std/localization/locale.categories/category.numeric/locale.num.get/facet.num.get.members/get_long_double.pass.cpp index e2b2aeafd1ef..9617899f749c 100644 --- a/libcxx/test/std/localization/locale.categories/category.numeric/locale.num.get/facet.num.get.members/get_long_double.pass.cpp +++ b/libcxx/test/std/localization/locale.categories/category.numeric/locale.num.get/facet.num.get.members/get_long_double.pass.cpp @@ -6,6 +6,11 @@ // //===----------------------------------------------------------------------===// +// The fix for LWG2381 (https://github.com/llvm/llvm-project/pull/77948) changed +// behavior of FP parsing, while Apple back-deployment targets remain broken due +// to the dylib. +// UNSUPPORTED: using-built-library-before-llvm-19 + // // class num_get @@ -105,9 +110,9 @@ int main(int, char**) f.get(cpp17_input_iterator(str), cpp17_input_iterator(str+sizeof(str)), ios, err, v); - assert(base(iter) == str+sizeof(str)-1); - assert(err == ios.goodbit); - assert(v == INFINITY); + assert(base(iter) == str); + assert(err == ios.failbit); + assert(v == 0.0l); } { const char str[] = "INF"; @@ -117,9 +122,9 @@ int main(int, char**) f.get(cpp17_input_iterator(str), cpp17_input_iterator(str+sizeof(str)), ios, err, v); - assert(base(iter) == str+sizeof(str)-1); - assert(err == ios.goodbit); - assert(v == INFINITY); + assert(base(iter) == str); + assert(err == ios.failbit); + assert(v == 0.0l); } { const char str[] = "-inf"; @@ -129,9 +134,9 @@ int main(int, char**) f.get(cpp17_input_iterator(str), cpp17_input_iterator(str+sizeof(str)), ios, err, v); - assert(base(iter) == str+sizeof(str)-1); - assert(err == ios.goodbit); - assert(v == -INFINITY); + assert(base(iter) == str + 1); + assert(err == ios.failbit); + assert(v == 0.0l); } { const char str[] = "-INF"; @@ -141,9 +146,9 @@ int main(int, char**) f.get(cpp17_input_iterator(str), cpp17_input_iterator(str+sizeof(str)), ios, err, v); - assert(base(iter) == str+sizeof(str)-1); - assert(err == ios.goodbit); - assert(v == -INFINITY); + assert(base(iter) == str + 1); + assert(err == ios.failbit); + assert(v == 0.0l); } { const char str[] = "nan"; @@ -153,9 +158,9 @@ int main(int, char**) f.get(cpp17_input_iterator(str), cpp17_input_iterator(str+sizeof(str)), ios, err, v); - assert(base(iter) == str+sizeof(str)-1); - assert(err == ios.goodbit); - assert(std::isnan(v)); + assert(base(iter) == str); + assert(err == ios.failbit); + assert(v == 0.0l); } { const char str[] = "NAN"; @@ -165,9 +170,129 @@ int main(int, char**) f.get(cpp17_input_iterator(str), cpp17_input_iterator(str+sizeof(str)), ios, err, v); - assert(base(iter) == str+sizeof(str)-1); - assert(err == ios.goodbit); - assert(std::isnan(v)); + assert(base(iter) == str); + assert(err == ios.failbit); + assert(v == 0.0l); + } + { + const char str[] = "p00"; + std::hex(ios); + std::ios_base::iostate err = ios.goodbit; + cpp17_input_iterator iter = f.get( + cpp17_input_iterator(str), cpp17_input_iterator(str + sizeof(str)), ios, err, v); + assert(base(iter) == str); + assert(err == ios.failbit); + assert(v == 0.0l); + } + { + const char str[] = "P00"; + std::hex(ios); + std::ios_base::iostate err = ios.goodbit; + cpp17_input_iterator iter = f.get( + cpp17_input_iterator(str), cpp17_input_iterator(str + sizeof(str)), ios, err, v); + assert(base(iter) == str); + assert(err == ios.failbit); + assert(v == 0.0l); + } + { + const char str[] = "+p00"; + std::hex(ios); + std::ios_base::iostate err = ios.goodbit; + cpp17_input_iterator iter = f.get( + cpp17_input_iterator(str), cpp17_input_iterator(str + sizeof(str)), ios, err, v); + assert(base(iter) == str + 1); + assert(err == ios.failbit); + assert(v == 0.0l); + } + { + const char str[] = "+P00"; + std::hex(ios); + std::ios_base::iostate err = ios.goodbit; + cpp17_input_iterator iter = f.get( + cpp17_input_iterator(str), cpp17_input_iterator(str + sizeof(str)), ios, err, v); + assert(base(iter) == str + 1); + assert(err == ios.failbit); + assert(v == 0.0l); + } + { + const char str[] = "-p00"; + std::hex(ios); + std::ios_base::iostate err = ios.goodbit; + cpp17_input_iterator iter = f.get( + cpp17_input_iterator(str), cpp17_input_iterator(str + sizeof(str)), ios, err, v); + assert(base(iter) == str + 1); + assert(err == ios.failbit); + assert(v == 0.0l); + } + { + const char str[] = "-P00"; + std::hex(ios); + std::ios_base::iostate err = ios.goodbit; + cpp17_input_iterator iter = f.get( + cpp17_input_iterator(str), cpp17_input_iterator(str + sizeof(str)), ios, err, v); + assert(base(iter) == str + 1); + assert(err == ios.failbit); + assert(v == 0.0l); + } + { + const char str[] = "e00"; + std::hex(ios); + std::ios_base::iostate err = ios.goodbit; + cpp17_input_iterator iter = f.get( + cpp17_input_iterator(str), cpp17_input_iterator(str + sizeof(str)), ios, err, v); + assert(base(iter) == str); + assert(err == ios.failbit); + assert(v == 0.0l); + } + { + const char str[] = "E00"; + std::hex(ios); + std::ios_base::iostate err = ios.goodbit; + cpp17_input_iterator iter = f.get( + cpp17_input_iterator(str), cpp17_input_iterator(str + sizeof(str)), ios, err, v); + assert(base(iter) == str); + assert(err == ios.failbit); + assert(v == 0.0l); + } + { + const char str[] = "+e00"; + std::hex(ios); + std::ios_base::iostate err = ios.goodbit; + cpp17_input_iterator iter = f.get( + cpp17_input_iterator(str), cpp17_input_iterator(str + sizeof(str)), ios, err, v); + assert(base(iter) == str + 1); + assert(err == ios.failbit); + assert(v == 0.0l); + } + { + const char str[] = "+E00"; + std::hex(ios); + std::ios_base::iostate err = ios.goodbit; + cpp17_input_iterator iter = f.get( + cpp17_input_iterator(str), cpp17_input_iterator(str + sizeof(str)), ios, err, v); + assert(base(iter) == str + 1); + assert(err == ios.failbit); + assert(v == 0.0l); + } + { + const char str[] = "-e00"; + std::hex(ios); + std::ios_base::iostate err = ios.goodbit; + cpp17_input_iterator iter = f.get( + cpp17_input_iterator(str), cpp17_input_iterator(str + sizeof(str)), ios, err, v); + assert(base(iter) == str + 1); + assert(err == ios.failbit); + assert(v == 0.0l); + } + { + const char str[] = "-E00"; + std::hex(ios); + std::ios_base::iostate err = ios.goodbit; + cpp17_input_iterator iter = f.get( + cpp17_input_iterator(str), cpp17_input_iterator(str + sizeof(str)), ios, err, v); + assert(base(iter) == str + 1); + assert(err == ios.failbit); + assert(v == 0.0l); } { const char str[] = "1.189731495357231765021264e+49321"; -- GitLab From 98f105a1304e8d3fd0a0234d1d488ed513833df8 Mon Sep 17 00:00:00 2001 From: Dave Lee Date: Tue, 21 May 2024 10:16:51 -0700 Subject: [PATCH 013/452] [lldb] Add the word "backtrace" to bt help string (#92618) We noticed that `apropos backtrace` did not return the `bt` alias. This change adds the word "backtrace" to the help for `bt`. It also updates `thread backtrace` to keep the language used roughly in sync. --- lldb/source/Commands/CommandObjectThread.cpp | 4 ++-- lldb/source/Interpreter/CommandInterpreter.cpp | 10 +++++----- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/lldb/source/Commands/CommandObjectThread.cpp b/lldb/source/Commands/CommandObjectThread.cpp index 4397ee14ea07..db96ee2cec38 100644 --- a/lldb/source/Commands/CommandObjectThread.cpp +++ b/lldb/source/Commands/CommandObjectThread.cpp @@ -114,8 +114,8 @@ public: CommandObjectThreadBacktrace(CommandInterpreter &interpreter) : CommandObjectIterateOverThreads( interpreter, "thread backtrace", - "Show thread call stacks. Defaults to the current thread, thread " - "indexes can be specified as arguments.\n" + "Show backtraces of thread call stacks. Defaults to the current " + "thread, thread indexes can be specified as arguments.\n" "Use the thread-index \"all\" to see all threads.\n" "Use the thread-index \"unique\" to see threads grouped by unique " "call stacks.\n" diff --git a/lldb/source/Interpreter/CommandInterpreter.cpp b/lldb/source/Interpreter/CommandInterpreter.cpp index 811726e30af4..7f21f382adb8 100644 --- a/lldb/source/Interpreter/CommandInterpreter.cpp +++ b/lldb/source/Interpreter/CommandInterpreter.cpp @@ -828,11 +828,11 @@ void CommandInterpreter::LoadCommandDictionary() { std::unique_ptr bt_regex_cmd_up( new CommandObjectRegexCommand( *this, "_regexp-bt", - "Show the current thread's call stack. Any numeric argument " - "displays at most that many " - "frames. The argument 'all' displays all threads. Use 'settings" - " set frame-format' to customize the printing of individual frames " - "and 'settings set thread-format' to customize the thread header.", + "Show backtrace of the current thread's call stack. Any numeric " + "argument displays at most that many frames. The argument 'all' " + "displays all threads. Use 'settings set frame-format' to customize " + "the printing of individual frames and 'settings set thread-format' " + "to customize the thread header.", "bt [ | all]", 0, false)); if (bt_regex_cmd_up) { // accept but don't document "bt -c " -- before bt was a regex -- GitLab From 253c28fa829cee0104c2fc59ed1a958980b5138c Mon Sep 17 00:00:00 2001 From: Vassil Vassilev Date: Tue, 21 May 2024 20:21:32 +0300 Subject: [PATCH 014/452] [clang-repl] Extend the C support. (#89804) The IdResolver chain is the main way for C to implement lookup rules. Every new partial translation unit caused clang to exit the top-most scope which in turn cleaned up the IdResolver chain. That was not an issue for C++ because its lookup is implemented on the level of declaration contexts. This patch keeps the IdResolver chain across partial translation units maintaining proper C-style lookup infrastructure. --- clang/lib/Interpreter/IncrementalParser.cpp | 13 +++++++++++-- clang/lib/Sema/SemaDecl.cpp | 10 +++++++--- clang/test/Interpreter/execute.c | 21 +++++++++++++++++++++ 3 files changed, 39 insertions(+), 5 deletions(-) create mode 100644 clang/test/Interpreter/execute.c diff --git a/clang/lib/Interpreter/IncrementalParser.cpp b/clang/lib/Interpreter/IncrementalParser.cpp index ef90fe9e6f54..5bc8385d874a 100644 --- a/clang/lib/Interpreter/IncrementalParser.cpp +++ b/clang/lib/Interpreter/IncrementalParser.cpp @@ -387,8 +387,7 @@ std::unique_ptr IncrementalParser::GenModule() { void IncrementalParser::CleanUpPTU(PartialTranslationUnit &PTU) { TranslationUnitDecl *MostRecentTU = PTU.TUPart; - TranslationUnitDecl *FirstTU = MostRecentTU->getFirstDecl(); - if (StoredDeclsMap *Map = FirstTU->getPrimaryContext()->getLookupPtr()) { + if (StoredDeclsMap *Map = MostRecentTU->getPrimaryContext()->getLookupPtr()) { for (auto &&[Key, List] : *Map) { DeclContextLookupResult R = List.getLookupResult(); std::vector NamedDeclsToRemove; @@ -407,6 +406,16 @@ void IncrementalParser::CleanUpPTU(PartialTranslationUnit &PTU) { } } } + + // FIXME: We should de-allocate MostRecentTU + for (Decl *D : MostRecentTU->decls()) { + auto *ND = dyn_cast(D); + if (!ND) + continue; + // Check if we need to clean up the IdResolver chain. + if (ND->getDeclName().getFETokenInfo()) + getCI()->getSema().IdResolver.RemoveDecl(ND); + } } llvm::StringRef IncrementalParser::GetMangledName(GlobalDecl GD) const { diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index 6764a979168d..7f6921ea22be 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -2282,9 +2282,13 @@ void Sema::ActOnPopScope(SourceLocation Loc, Scope *S) { if (LabelDecl *LD = dyn_cast(D)) CheckPoppedLabel(LD, *this, addDiag); - // Remove this name from our lexical scope, and warn on it if we haven't - // already. - IdResolver.RemoveDecl(D); + // Partial translation units that are created in incremental processing must + // not clean up the IdResolver because PTUs should take into account the + // declarations that came from previous PTUs. + if (!PP.isIncrementalProcessingEnabled()) + IdResolver.RemoveDecl(D); + + // Warn on it if we are shadowing a declaration. auto ShadowI = ShadowingDecls.find(D); if (ShadowI != ShadowingDecls.end()) { if (const auto *FD = dyn_cast(ShadowI->second)) { diff --git a/clang/test/Interpreter/execute.c b/clang/test/Interpreter/execute.c new file mode 100644 index 000000000000..44a3a32c9301 --- /dev/null +++ b/clang/test/Interpreter/execute.c @@ -0,0 +1,21 @@ +// REQUIRES: host-supports-jit +// UNSUPPORTED: system-aix + +// RUN: cat %s | clang-repl -Xcc -xc -Xcc -Xclang -Xcc -verify | FileCheck %s +// RUN: cat %s | clang-repl -Xcc -xc -Xcc -O2 -Xcc -Xclang -Xcc -verify| FileCheck %s +int printf(const char *, ...); +int i = 42; err // expected-error{{use of undeclared identifier}} +int i = 42; +struct S { float f; struct S *m;} s = {1.0, 0}; +// FIXME: Making foo inline fails to emit the function. +int foo() { return 42; } +void run() { \ + printf("i = %d\n", i); \ + printf("S[f=%f, m=0x%llx]\n", s.f, (unsigned long long)s.m); \ + int r3 = foo(); \ +} +run(); +// CHECK: i = 42 +// CHECK-NEXT: S[f=1.000000, m=0x0] + +%quit -- GitLab From 315a83145b6d83134eee49570632f3ee2a5a38a9 Mon Sep 17 00:00:00 2001 From: Konstantin Zhuravlyov Date: Tue, 21 May 2024 13:35:39 -0400 Subject: [PATCH 015/452] AMDGPU/NFC: Reserve 0x056 and 0x057 EF_AMDGPU_MACHs (#92917) --- llvm/docs/AMDGPUUsage.rst | 2 ++ llvm/include/llvm/BinaryFormat/ELF.h | 4 +++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/llvm/docs/AMDGPUUsage.rst b/llvm/docs/AMDGPUUsage.rst index 75536bc5bea6..1004956ac8f1 100644 --- a/llvm/docs/AMDGPUUsage.rst +++ b/llvm/docs/AMDGPUUsage.rst @@ -1970,6 +1970,8 @@ The AMDGPU backend uses the following ELF header: ``EF_AMDGPU_MACH_AMDGCN_GFX10_3_GENERIC`` 0x053 ``gfx10-3-generic`` ``EF_AMDGPU_MACH_AMDGCN_GFX11_GENERIC`` 0x054 ``gfx11-generic`` *reserved* 0x055 Reserved. + *reserved* 0x056 Reserved. + *reserved* 0x057 Reserved. ========================================== ========== ============================= Sections diff --git a/llvm/include/llvm/BinaryFormat/ELF.h b/llvm/include/llvm/BinaryFormat/ELF.h index f296acc2ca4b..67cacaed2e12 100644 --- a/llvm/include/llvm/BinaryFormat/ELF.h +++ b/llvm/include/llvm/BinaryFormat/ELF.h @@ -796,11 +796,13 @@ enum : unsigned { EF_AMDGPU_MACH_AMDGCN_GFX10_3_GENERIC = 0x053, EF_AMDGPU_MACH_AMDGCN_GFX11_GENERIC = 0x054, EF_AMDGPU_MACH_AMDGCN_RESERVED_0X55 = 0x055, + EF_AMDGPU_MACH_AMDGCN_RESERVED_0X56 = 0x056, + EF_AMDGPU_MACH_AMDGCN_RESERVED_0X57 = 0x057, // clang-format on // First/last AMDGCN-based processors. EF_AMDGPU_MACH_AMDGCN_FIRST = EF_AMDGPU_MACH_AMDGCN_GFX600, - EF_AMDGPU_MACH_AMDGCN_LAST = EF_AMDGPU_MACH_AMDGCN_GFX11_GENERIC, + EF_AMDGPU_MACH_AMDGCN_LAST = EF_AMDGPU_MACH_AMDGCN_RESERVED_0X57, // Indicates if the "xnack" target feature is enabled for all code contained // in the object. -- GitLab From 70fc23946bc241a154c13140af9a597049715723 Mon Sep 17 00:00:00 2001 From: Matt Arsenault Date: Mon, 1 Apr 2024 18:02:38 +0300 Subject: [PATCH 016/452] RegisterPressure: Check empty instead of size == 0 --- llvm/lib/CodeGen/RegisterPressure.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/llvm/lib/CodeGen/RegisterPressure.cpp b/llvm/lib/CodeGen/RegisterPressure.cpp index 3fa22447f416..01042860ca9f 100644 --- a/llvm/lib/CodeGen/RegisterPressure.cpp +++ b/llvm/lib/CodeGen/RegisterPressure.cpp @@ -1041,7 +1041,7 @@ void RegPressureTracker::bumpUpwardPressure(const MachineInstr *MI) { // Account for register pressure similar to RegPressureTracker::recede(). RegisterOperands RegOpers; RegOpers.collect(*MI, *TRI, *MRI, TrackLaneMasks, /*IgnoreDead=*/true); - assert(RegOpers.DeadDefs.size() == 0); + assert(RegOpers.DeadDefs.empty()); if (TrackLaneMasks) RegOpers.adjustLaneLiveness(*LIS, *MRI, SlotIdx); else if (RequireIntervals) -- GitLab From 2805e6faad7795ed0846010e3e7ad41460030758 Mon Sep 17 00:00:00 2001 From: Jordan Rupprecht Date: Tue, 21 May 2024 12:51:58 -0500 Subject: [PATCH 017/452] [llvm-driver] Add driver alias for c++filt (#92803) Similar to 9d955a63c7b0d2d547a63d4074e03cd5ebd1f162, this allows the driver to respond to `c++filt`. --- llvm/test/tools/llvm-driver/symlink-call.test | 2 ++ llvm/tools/llvm-cxxfilt/CMakeLists.txt | 4 ++++ utils/bazel/llvm-project-overlay/llvm/driver.bzl | 1 + 3 files changed, 7 insertions(+) diff --git a/llvm/test/tools/llvm-driver/symlink-call.test b/llvm/test/tools/llvm-driver/symlink-call.test index eeedf9edc73f..ca6098216b13 100644 --- a/llvm/test/tools/llvm-driver/symlink-call.test +++ b/llvm/test/tools/llvm-driver/symlink-call.test @@ -14,6 +14,8 @@ # RUN: %t/cxxfilt-15 --help | FileCheck %s # RUN: ln -s %llvm %t/cxxfilt-15.exe # RUN: %t/cxxfilt-15.exe --help | FileCheck %s +# RUN: ln -s %llvm %t/c++filt +# RUN: %t/c++filt --help | FileCheck %s # RUN: ln -s %llvm %t/llvm-15 # RUN: %t/llvm-15 cxxfilt --help | FileCheck %s diff --git a/llvm/tools/llvm-cxxfilt/CMakeLists.txt b/llvm/tools/llvm-cxxfilt/CMakeLists.txt index cbc4c2db6154..a644baffdd90 100644 --- a/llvm/tools/llvm-cxxfilt/CMakeLists.txt +++ b/llvm/tools/llvm-cxxfilt/CMakeLists.txt @@ -17,6 +17,10 @@ add_llvm_tool(llvm-cxxfilt GENERATE_DRIVER ) +if(LLVM_TOOL_LLVM_DRIVER_BUILD) + set_property(GLOBAL APPEND PROPERTY LLVM_DRIVER_HIDDEN_TOOL_ALIASES_llvm-cxxfilt c++filt) +endif() + if(LLVM_INSTALL_BINUTILS_SYMLINKS) add_llvm_tool_symlink(c++filt llvm-cxxfilt) endif() diff --git a/utils/bazel/llvm-project-overlay/llvm/driver.bzl b/utils/bazel/llvm-project-overlay/llvm/driver.bzl index 10796d919834..a57a14ebd5f8 100644 --- a/utils/bazel/llvm-project-overlay/llvm/driver.bzl +++ b/utils/bazel/llvm-project-overlay/llvm/driver.bzl @@ -39,6 +39,7 @@ _EXTRA_ALIASES = { "clang": ["clang++", "clang-cl", "clang-cpp"], "lld": ["ld", "lld-link", "ld.lld", "ld64.lld", "wasm-ld"], "llvm-ar": ["ranlib", "lib", "dlltool"], + "llvm-cxxfilt": ["c++filt"], "llvm-objcopy": ["bitcode-strip", "install-name-tool", "strip"], "llvm-objdump": ["otool"], "llvm-rc": ["windres"], -- GitLab From 194e7cc7aabe2ffb153ca66527ffb6b500fa4c50 Mon Sep 17 00:00:00 2001 From: Zaara Syeda Date: Tue, 21 May 2024 14:00:24 -0400 Subject: [PATCH 018/452] [PowerPC][AIX] 64-bit large code-model support for toc-data (#90619) This patch adds support for toc-data for 64-bit large code-model on AIX. The sequence ADDIStocHA8/ADDItocL8 is used to access the data directly from the TOC. When emitting the instruction ADDIStocHA8, we check if the symbol has toc-data attribute before creating a toc entry for it. When emitting the instruction ADDItocL8, we use the LA8 instruction to load the address. --- .../clang/Basic/DiagnosticDriverKinds.td | 3 - clang/lib/Driver/ToolChains/AIX.cpp | 8 --- clang/test/Driver/tocdata-cc1.c | 17 ++--- llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp | 16 ++--- llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp | 29 ++++---- llvm/lib/Target/PowerPC/PPCInstrInfo.cpp | 6 ++ llvm/lib/Target/PowerPC/PPCInstrInfo.td | 2 +- llvm/test/CodeGen/PowerPC/toc-data.ll | 67 +++++++++++++++++++ 8 files changed, 104 insertions(+), 44 deletions(-) diff --git a/clang/include/clang/Basic/DiagnosticDriverKinds.td b/clang/include/clang/Basic/DiagnosticDriverKinds.td index 9d97a75f696f..50d3b42c0f86 100644 --- a/clang/include/clang/Basic/DiagnosticDriverKinds.td +++ b/clang/include/clang/Basic/DiagnosticDriverKinds.td @@ -599,9 +599,6 @@ def warn_drv_unsupported_gpopt : Warning< "ignoring '-mgpopt' option as it cannot be used with %select{|the implicit" " usage of }0-mabicalls">, InGroup; -def warn_drv_unsupported_tocdata: Warning< - "ignoring '-mtocdata' as it is only supported for -mcmodel=small">, - InGroup; def warn_drv_unsupported_sdata : Warning< "ignoring '-msmall-data-limit=' with -mcmodel=large for -fpic or RV64">, InGroup; diff --git a/clang/lib/Driver/ToolChains/AIX.cpp b/clang/lib/Driver/ToolChains/AIX.cpp index 85825e1ea65b..381d72e045b9 100644 --- a/clang/lib/Driver/ToolChains/AIX.cpp +++ b/clang/lib/Driver/ToolChains/AIX.cpp @@ -479,14 +479,6 @@ static void addTocDataOptions(const llvm::opt::ArgList &Args, return false; }(); - // Currently only supported for small code model. - if (TOCDataGloballyinEffect && - (Args.getLastArgValue(options::OPT_mcmodel_EQ) == "large" || - Args.getLastArgValue(options::OPT_mcmodel_EQ) == "medium")) { - D.Diag(clang::diag::warn_drv_unsupported_tocdata); - return; - } - enum TOCDataSetting { AddressInTOC = 0, // Address of the symbol stored in the TOC. DataInTOC = 1 // Symbol defined in the TOC. diff --git a/clang/test/Driver/tocdata-cc1.c b/clang/test/Driver/tocdata-cc1.c index fe0d97ea02db..e00383deecef 100644 --- a/clang/test/Driver/tocdata-cc1.c +++ b/clang/test/Driver/tocdata-cc1.c @@ -1,16 +1,13 @@ // RUN: %clang -### --target=powerpc-ibm-aix-xcoff -mcmodel=medium -mtocdata %s 2>&1 \ -// RUN: | FileCheck -check-prefix=CHECK-NOTOC %s +// RUN: | FileCheck %s // RUN: %clang -### --target=powerpc-ibm-aix-xcoff -mcmodel=large -mtocdata %s 2>&1 \ -// RUN: | FileCheck -check-prefix=CHECK-NOTOC %s +// RUN: | FileCheck %s // RUN: %clang -### --target=powerpc-ibm-aix-xcoff -mtocdata %s 2>&1 \ -// RUN: | FileCheck -check-prefix=CHECK-TOC %s +// RUN: | FileCheck %s // RUN: %clang -### --target=powerpc64-ibm-aix-xcoff -mcmodel=medium -mtocdata %s 2>&1 \ -// RUN: | FileCheck -check-prefix=CHECK-NOTOC %s +// RUN: | FileCheck %s // RUN: %clang -### --target=powerpc64-ibm-aix-xcoff -mcmodel=large -mtocdata %s 2>&1 \ -// RUN: | FileCheck -check-prefix=CHECK-NOTOC %s +// RUN: | FileCheck %s // RUN: %clang -### --target=powerpc64-ibm-aix-xcoff -mtocdata %s 2>&1 \ -// RUN: | FileCheck -check-prefix=CHECK-TOC %s -// CHECK-NOTOC: warning: ignoring '-mtocdata' as it is only supported for -mcmodel=small -// CHECK-NOTOC-NOT: "-cc1"{{.*}}" "-mtocdata" -// CHECK-TOC: "-cc1"{{.*}}" "-mtocdata" -// CHECK-TOC-NOT: warning: ignoring '-mtocdata' as it is only supported for -mcmodel=small +// RUN: | FileCheck %s +// CHECK: "-cc1"{{.*}}" "-mtocdata" diff --git a/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp b/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp index ac48dc5af9d5..72e8215fffaf 100644 --- a/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp +++ b/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp @@ -1157,12 +1157,12 @@ void PPCAsmPrinter::emitInstruction(const MachineInstr *MI) { MCSymbolRefExpr::VariantKind VK = GetVKForMO(MO); - // If the symbol isn't toc-data then use the TOC on AIX. // Map the global address operand to be a reference to the TOC entry we // will synthesize later. 'TOCEntry' is a label used to reference the // storage allocated in the TOC which contains the address of 'MOSymbol'. - // If the toc-data attribute is used, the TOC entry contains the data - // rather than the address of the MOSymbol. + // If the symbol does not have the toc-data attribute, then we create the + // TOC entry on AIX. If the toc-data attribute is used, the TOC entry + // contains the data rather than the address of the MOSymbol. if (![](const MachineOperand &MO) { if (!MO.isGlobal()) return false; @@ -1170,7 +1170,6 @@ void PPCAsmPrinter::emitInstruction(const MachineInstr *MI) { const GlobalVariable *GV = dyn_cast(MO.getGlobal()); if (!GV) return false; - return GV->hasAttribute("toc-data"); }(MO)) { MOSymbol = lookUpOrCreateTOCEntry(MOSymbol, getTOCEntryTypeForMO(MO), VK); @@ -1301,8 +1300,10 @@ void PPCAsmPrinter::emitInstruction(const MachineInstr *MI) { unsigned Op = MI->getOpcode(); - // Change the opcode to load address for tocdata - TmpInst.setOpcode(Op == PPC::ADDItocL8 ? PPC::ADDI8 : PPC::LA); + // Change the opcode to load address for toc-data. + // ADDItocL is only used for 32-bit toc-data on AIX and will always use LA. + TmpInst.setOpcode(Op == PPC::ADDItocL8 ? (IsAIX ? PPC::LA8 : PPC::ADDI8) + : PPC::LA); const MachineOperand &MO = MI->getOperand(2); assert((Op == PPC::ADDItocL8) @@ -1316,8 +1317,7 @@ void PPCAsmPrinter::emitInstruction(const MachineInstr *MI) { const MCExpr *Exp = MCSymbolRefExpr::create( MOSymbol, - Op == PPC::ADDItocL8 ? MCSymbolRefExpr::VK_PPC_TOC_LO - : MCSymbolRefExpr::VK_PPC_L, + IsAIX ? MCSymbolRefExpr::VK_PPC_L : MCSymbolRefExpr::VK_PPC_TOC_LO, OutContext); TmpInst.getOperand(2) = MCOperand::createExpr(Exp); diff --git a/llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp b/llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp index 68621558e3fa..26560dc5cdeb 100644 --- a/llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp +++ b/llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp @@ -6143,23 +6143,22 @@ void PPCDAGToDAGISel::Select(SDNode *N) { " ELF/AIX or 32-bit AIX in the following."); // Transforms the ISD::TOC_ENTRY node for 32-bit AIX large code model mode, - // or 64-bit medium (ELF-only), or large (ELF and AIX) code model code that - // does not conain TOC data symbols. - // We generate two instructions as described below. The first source - // operand is a symbol reference. If it must be referenced via the toc - // according to Subtarget, we generate: + // 64-bit medium (ELF-only), or 64-bit large (ELF and AIX) code model code + // that does not contain TOC data symbols. We generate two instructions as + // described below. The first source operand is a symbol reference. If it + // must be referenced via the TOC according to Subtarget, we generate: // [32-bit AIX] // LWZtocL(@sym, ADDIStocHA(%r2, @sym)) // [64-bit ELF/AIX] // LDtocL(@sym, ADDIStocHA8(%x2, @sym)) - // Otherwise we generate: + // Otherwise for medium code model ELF we generate: // ADDItocL8(ADDIStocHA8(%x2, @sym), @sym) - // For large code model with TOC data symbols we generate: + // And finally for AIX with toc-data we generate: // [32-bit AIX] // ADDItocL(ADDIStocHA(%x2, @sym), @sym) // [64-bit AIX] - // Currently not supported. + // ADDItocL8(ADDIStocHA8(%x2, @sym), @sym) SDValue GA = N->getOperand(0); SDValue TOCbase = N->getOperand(1); @@ -6171,12 +6170,9 @@ void PPCDAGToDAGISel::Select(SDNode *N) { // On AIX, if the symbol has the toc-data attribute it will be defined // in the TOC entry, so we use an ADDItocL/ADDItocL8. if (isAIXABI && hasTocDataAttr(GA)) { - if (isPPC64) - report_fatal_error( - "64-bit large code model toc-data not yet supported"); - - ReplaceNode(N, CurDAG->getMachineNode(PPC::ADDItocL, dl, VT, - SDValue(Tmp, 0), GA)); + ReplaceNode( + N, CurDAG->getMachineNode(isPPC64 ? PPC::ADDItocL8 : PPC::ADDItocL, + dl, VT, SDValue(Tmp, 0), GA)); return; } @@ -6191,6 +6187,7 @@ void PPCDAGToDAGISel::Select(SDNode *N) { return; } + assert(isPPC64 && "TOC_ENTRY already handled for 32-bit."); // Build the address relative to the TOC-pointer. ReplaceNode(N, CurDAG->getMachineNode(PPC::ADDItocL8, dl, MVT::i64, SDValue(Tmp, 0), GA)); @@ -7777,6 +7774,10 @@ void PPCDAGToDAGISel::PeepholePPC64() { Flags = PPCII::MO_TLSLD_LO; break; case PPC::ADDItocL8: + // Skip the following peephole optimizations for ADDItocL8 on AIX which + // is used for toc-data access. + if (Subtarget->isAIXABI()) + continue; Flags = PPCII::MO_TOC_LO; break; } diff --git a/llvm/lib/Target/PowerPC/PPCInstrInfo.cpp b/llvm/lib/Target/PowerPC/PPCInstrInfo.cpp index 9e56de732c58..85bbfabf5d3c 100644 --- a/llvm/lib/Target/PowerPC/PPCInstrInfo.cpp +++ b/llvm/lib/Target/PowerPC/PPCInstrInfo.cpp @@ -4438,6 +4438,12 @@ bool PPCInstrInfo::isDefMIElgibleForForwarding(MachineInstr &DefMI, if (Opc != PPC::ADDItocL8 && Opc != PPC::ADDI && Opc != PPC::ADDI8) return false; + // Skip the optimization of transformTo[NewImm|Imm]FormFedByAdd for ADDItocL8 + // on AIX which is used for toc-data access. TODO: Follow up to see if it can + // apply for AIX toc-data as well. + if (Opc == PPC::ADDItocL8 && Subtarget.isAIX()) + return false; + assert(DefMI.getNumOperands() >= 3 && "Add inst must have at least three operands"); RegMO = &DefMI.getOperand(1); diff --git a/llvm/lib/Target/PowerPC/PPCInstrInfo.td b/llvm/lib/Target/PowerPC/PPCInstrInfo.td index 7929a781dbda..e3d6d2f094f2 100644 --- a/llvm/lib/Target/PowerPC/PPCInstrInfo.td +++ b/llvm/lib/Target/PowerPC/PPCInstrInfo.td @@ -3346,7 +3346,7 @@ def ADDIStocHA : PPCEmitTimePseudo<(outs gprc:$rD), (ins gprc_nor0:$reg, tocentr "#ADDIStocHA", [(set i32:$rD, (PPCtoc_entry i32:$reg, tglobaladdr:$disp))]>; -// TOC Data Transform AIX +// TOC Data Transform on AIX def ADDItoc : PPCEmitTimePseudo<(outs gprc:$rD), (ins tocentry32:$disp, gprc:$reg), "#ADDItoc", [(set i32:$rD, diff --git a/llvm/test/CodeGen/PowerPC/toc-data.ll b/llvm/test/CodeGen/PowerPC/toc-data.ll index 7f7afe76cfcd..1a1078095452 100644 --- a/llvm/test/CodeGen/PowerPC/toc-data.ll +++ b/llvm/test/CodeGen/PowerPC/toc-data.ll @@ -16,6 +16,10 @@ ; RUN: -stop-before=ppc-vsx-copy | FileCheck %s --check-prefix CHECK32LARGE ; RUN: llc -mtriple powerpc-ibm-aix-xcoff -code-model=large -verify-machineinstrs < %s | FileCheck %s --check-prefix TEST32LARGE +; RUN: llc -mtriple powerpc64-ibm-aix-xcoff -code-model=large -verify-machineinstrs < %s \ +; RUN: -stop-before=ppc-vsx-copy | FileCheck %s --check-prefix CHECK64LARGE +; RUN: llc -mtriple powerpc64-ibm-aix-xcoff -code-model=large -verify-machineinstrs < %s | FileCheck %s --check-prefix TEST64LARGE + ; Global variables i and f have the toc-data attribute. ; In the following functions, those writing to or reading from ; variables i and f should use the toc-data access pattern. @@ -63,6 +67,17 @@ define dso_local void @write_int(i32 signext %in) { ; TEST32LARGE-NEXT: la 4, i[TD]@l(4) ; TEST32LARGE-NEXT: stw 3, 0(4) + +; CHECK64LARGE: name: write_int +; CHECK64LARGE: %[[SCRATCH1:[0-9]+]]:g8rc_and_g8rc_nox0 = ADDIStocHA8 $x2, @i +; CHECK64LARGE-NEXT: %[[SCRATCH2:[0-9]+]]:g8rc_and_g8rc_nox0 = ADDItocL8 killed %[[SCRATCH1]], @i +; CHECK64LARGE-NEXT: STW8 %{{[0-9]+}}, 0, killed %[[SCRATCH2]] :: (store (s32) into @i) + +; TEST64LARGE: .write_int: +; TEST64LARGE: addis 4, i[TD]@u(2) +; TEST64LARGE-NEXT: la 4, i[TD]@l(4) +; TEST64LARGE-NEXT: stw 3, 0(4) + define dso_local i64 @read_ll() { entry: %0 = load i64, ptr @ll, align 8 @@ -98,6 +113,15 @@ define dso_local i64 @read_ll() { ; TEST32LARGE-NEXT: lwz 3, 0(4) ; TEST32LARGE-NEXT: lwz 4, 4(4) +; CHECK64LARGE: name: read_ll +; CHECK64LARGE: %[[SCRATCH1:[0-9]+]]:g8rc_and_g8rc_nox0 = ADDIStocHA8 $x2, @ll +; CHECK64LARGE: LDtocL @ll, killed %[[SCRATCH1]] :: (load (s64) from got) + +; TEST64LARGE: .read_ll: +; TEST64LARGE: addis 3, L..C0@u(2) +; TEST64LARGE-NEXT: ld 3, L..C0@l(3) +; TEST64LARGE-NEXT: ld 3, 0(3) + define dso_local float @read_float() { entry: %0 = load float, ptr @f, align 4 @@ -134,6 +158,18 @@ define dso_local float @read_float() { ; TEST32LARGE-NEXT: la 3, f[TD]@l(3) ; TEST32LARGE-NEXT: lfs 1, 0(3) + +; CHECK64LARGE: name: read_float +; CHECK64LARGE: %[[SCRATCH1:[0-9]+]]:g8rc_and_g8rc_nox0 = ADDIStocHA8 $x2, @f +; CHECK64LARGE-NEXT: %[[SCRATCH2:[0-9]+]]:g8rc_and_g8rc_nox0 = ADDItocL8 killed %[[SCRATCH1]], @f +; CHECK64LARGE-NEXT: LFS 0, killed %[[SCRATCH2]] :: (dereferenceable load (s32) from @f) + + +; TEST64LARGE: .read_float: +; TEST64LARGE: addis 3, f[TD]@u(2) +; TEST64LARGE-NEXT: la 3, f[TD]@l(3) +; TEST64LARGE-NEXT: lfs 1, 0(3) + define dso_local void @write_double(double %in) { entry: store double %in, ptr @d, align 8 @@ -167,6 +203,15 @@ define dso_local void @write_double(double %in) { ; TEST32LARGE-NEXT: lwz 3, L..C1@l(3) ; TEST32LARGE-NEXT: stfd 1, 0(3) +; CHECK64LARGE: name: write_double +; CHECK64LARGE: %[[SCRATCH1:[0-9]+]]:g8rc_and_g8rc_nox0 = ADDIStocHA8 $x2, @d +; CHECK64LARGE: LDtocL @d, killed %[[SCRATCH1]] :: (load (s64) from got) + +; TEST64LARGE: .write_double: +; TEST64LARGE: addis 3, L..C1@u(2) +; TEST64LARGE-NEXT: ld 3, L..C1@l(3) +; TEST64LARGE-NEXT: stfd 1, 0(3) + define dso_local nonnull ptr @addr() { entry: ret ptr @i @@ -237,4 +282,26 @@ define dso_local nonnull ptr @addr() { ; TEST32LARGE-NEXT: .globl f[TD] ; TEST32LARGE-NOT: .tc f[TE],f[RW] +; CHECK64LARGE: name: addr +; CHECK64LARGE: %[[SCRATCH1:[0-9]+]]:g8rc_and_g8rc_nox0 = ADDIStocHA8 $x2, @i +; CHECK64LARGE-NEXT: %[[SCRATCH2:[0-9]+]]:g8rc = ADDItocL8 killed %[[SCRATCH1]], @i +; CHECK64LARGE-NEXT: $x3 = COPY %[[SCRATCH2]] + +; TEST64LARGE: .addr: +; TEST64LARGE: addis 3, i[TD]@u(2) +; TEST64LARGE: la 3, i[TD]@l(3) + +; TEST64LARGE: .toc +; TEST64LARGE: .tc ll[TE],ll[RW] +; TEST64LARGE-NOT: .csect ll[TD] +; TEST64LARGE: .tc d[TE],d[RW] +; TEST64LARGE-NOT: .csect d[TD],2 +; TEST64LARGE: .csect i[TD],2 +; TEST64LARGE-NEXT: .globl i[TD] +; TEST64LARGE-NEXT: .align 2 +; TEST64LARGE-NOT: .tc i[TE],i[RW] +; TEST64LARGE: .csect f[TD],2 +; TEST64LARGE-NEXT: .globl f[TD] +; TEST64LARGE-NOT: .tc f[TE],f[RW] + attributes #0 = { "toc-data" } -- GitLab From e6b14b6f8bfeeea8d24c8dccb17053ba491d5879 Mon Sep 17 00:00:00 2001 From: Vlad Serebrennikov Date: Tue, 21 May 2024 21:00:53 +0300 Subject: [PATCH 019/452] [clangd] Fix directory separators in `infinite-instantiation.test` Fixing https://lab.llvm.org/buildbot/#/builders/123/builds/26934 caused by #92888. Third time the charm! --- clang-tools-extra/clangd/test/infinite-instantiation.test | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clang-tools-extra/clangd/test/infinite-instantiation.test b/clang-tools-extra/clangd/test/infinite-instantiation.test index d379a9c2d523..a9c787c77027 100644 --- a/clang-tools-extra/clangd/test/infinite-instantiation.test +++ b/clang-tools-extra/clangd/test/infinite-instantiation.test @@ -1,5 +1,5 @@ // RUN: rm -rf %t.dir && mkdir -p %t.dir -// RUN: echo '[{"directory": "%/t.dir", "command": "clang -ftemplate-depth=100 -x c++ %s", "file": "%/s"}]' > %t.dir/compile_commands.json +// RUN: echo '[{"directory": "%/t.dir", "command": "clang -ftemplate-depth=100 -x c++ %/s", "file": "%/s"}]' > %t.dir/compile_commands.json // RUN: not clangd --compile-commands-dir=%t.dir -check=%s 2>&1 | FileCheck -strict-whitespace %s // CHECK: [template_recursion_depth_exceeded] -- GitLab From 3c3e71d929457daf4be425a35920cc53ed875fab Mon Sep 17 00:00:00 2001 From: Matt Arsenault Date: Tue, 2 Apr 2024 18:26:34 -0400 Subject: [PATCH 020/452] X86: Add regression test from issue #76416 Also add another testcase reported at the same regression commit. Make sure this assert is fixed when the patch is eventually reapplied. --- ...d-implicit-def-subreg-to-reg-regression.ll | 45 +++++++++++ llvm/test/CodeGen/X86/issue76416.ll | 78 +++++++++++++++++++ 2 files changed, 123 insertions(+) create mode 100644 llvm/test/CodeGen/X86/coalescer-add-implicit-def-subreg-to-reg-regression.ll create mode 100644 llvm/test/CodeGen/X86/issue76416.ll diff --git a/llvm/test/CodeGen/X86/coalescer-add-implicit-def-subreg-to-reg-regression.ll b/llvm/test/CodeGen/X86/coalescer-add-implicit-def-subreg-to-reg-regression.ll new file mode 100644 index 000000000000..0e6cb7a3aff2 --- /dev/null +++ b/llvm/test/CodeGen/X86/coalescer-add-implicit-def-subreg-to-reg-regression.ll @@ -0,0 +1,45 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 5 +; RUN: llc -mtriple=x86_64-unknown-linux-gnu < %s | FileCheck %s + +; Not from issue 76416, but separate testcase reported on the same +; regressing commit. +define void @other_regression(i1 %cmp.not.i.i.i) { +; CHECK-LABEL: other_regression: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: pushq %rax +; CHECK-NEXT: .cfi_def_cfa_offset 16 +; CHECK-NEXT: movl 0, %eax +; CHECK-NEXT: xorl %ecx, %ecx +; CHECK-NEXT: sarl %cl, %eax +; CHECK-NEXT: movl $1, %edx +; CHECK-NEXT: xorl %ecx, %ecx +; CHECK-NEXT: shrl %cl, %edx +; CHECK-NEXT: imull %eax, %edx +; CHECK-NEXT: movslq %edx, %rsi +; CHECK-NEXT: xorl %eax, %eax +; CHECK-NEXT: xorl %edi, %edi +; CHECK-NEXT: xorl %edx, %edx +; CHECK-NEXT: callq *%rax +entry: + br label %for.cond10.preheader + +trap: ; preds = %for.body13 + unreachable + +for.cond10.preheader: ; preds = %while.cond.i.i.i, %entry + %indvars.iv = phi i64 [ 0, %entry ], [ 1, %while.cond.i.i.i ] + %i = trunc i64 %indvars.iv to i32 + br label %for.body13 + +for.body13: ; preds = %for.cond10.preheader + %i1 = load i32, ptr null, align 4 + %shr = ashr i32 %i1, %i + %shr15 = ashr i32 1, %i + %mul16 = mul i32 %shr15, %shr + %conv = sext i32 %mul16 to i64 + call void null(ptr null, i64 %conv, ptr null) + br i1 false, label %while.cond.i.i.i, label %trap + +while.cond.i.i.i: ; preds = %while.cond.i.i.i, %for.body13 + br i1 %cmp.not.i.i.i, label %for.cond10.preheader, label %while.cond.i.i.i +} diff --git a/llvm/test/CodeGen/X86/issue76416.ll b/llvm/test/CodeGen/X86/issue76416.ll new file mode 100644 index 000000000000..d0f7fe684a84 --- /dev/null +++ b/llvm/test/CodeGen/X86/issue76416.ll @@ -0,0 +1,78 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 5 +; RUN: llc -mtriple=x86_64-unknown-freebsd15.0 < %s | FileCheck %s + +%struct.anon.5.28.78.99.149.119 = type { [4 x i8] } + +@vga_load_state_p = external dso_local global ptr, align 8 +@vga_load_state_data = external dso_local global i8, align 1 + +define dso_local void @vga_load_state() #0 { +; CHECK-LABEL: vga_load_state: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: movl $0, -{{[0-9]+}}(%rsp) +; CHECK-NEXT: cmpl $3, -{{[0-9]+}}(%rsp) +; CHECK-NEXT: jg .LBB0_3 +; CHECK-NEXT: .p2align 4, 0x90 +; CHECK-NEXT: .LBB0_2: # %for.body +; CHECK-NEXT: # =>This Inner Loop Header: Depth=1 +; CHECK-NEXT: xorl %eax, %eax +; CHECK-NEXT: #APP +; CHECK-NEXT: #NO_APP +; CHECK-NEXT: incl -{{[0-9]+}}(%rsp) +; CHECK-NEXT: cmpl $3, -{{[0-9]+}}(%rsp) +; CHECK-NEXT: jle .LBB0_2 +; CHECK-NEXT: .LBB0_3: # %for.end +; CHECK-NEXT: movl $0, -{{[0-9]+}}(%rsp) +; CHECK-NEXT: .p2align 4, 0x90 +; CHECK-NEXT: .LBB0_4: # %for.cond1 +; CHECK-NEXT: # =>This Inner Loop Header: Depth=1 +; CHECK-NEXT: #APP +; CHECK-NEXT: #NO_APP +; CHECK-NEXT: movq vga_load_state_p(%rip), %rax +; CHECK-NEXT: movslq -{{[0-9]+}}(%rsp), %rcx +; CHECK-NEXT: movzbl (%rax,%rcx), %eax +; CHECK-NEXT: movb %al, vga_load_state_data(%rip) +; CHECK-NEXT: leal 1(%rcx), %eax +; CHECK-NEXT: movl %eax, -{{[0-9]+}}(%rsp) +; CHECK-NEXT: jmp .LBB0_4 +entry: + %i = alloca i32, align 4 + store i32 0, ptr %i, align 4 + br label %for.cond + +for.cond: ; preds = %for.body, %entry + %i1 = load i32, ptr %i, align 4 + %cmp = icmp slt i32 %i1, 4 + br i1 %cmp, label %for.body, label %for.end + +for.body: ; preds = %for.cond + call void asm sideeffect "", "{ax},~{dirflag},~{fpsr},~{flags}"(i8 0) #1 + %i2 = load i32, ptr %i, align 4 + %inc = add nsw i32 %i2, 1 + store i32 %inc, ptr %i, align 4 + br label %for.cond + +for.end: ; preds = %for.cond + store i32 0, ptr %i, align 4 + br label %for.cond1 + +for.cond1: ; preds = %for.cond1, %for.end + call void asm sideeffect "", "N{dx},~{dirflag},~{fpsr},~{flags}"(i32 poison) #1 + %i3 = load ptr, ptr @vga_load_state_p, align 8 + %regs = getelementptr inbounds %struct.anon.5.28.78.99.149.119, ptr %i3, i32 0, i32 0 + %i4 = load i32, ptr %i, align 4 + %idxprom = sext i32 %i4 to i64 + %arrayidx = getelementptr inbounds [4 x i8], ptr %regs, i64 0, i64 %idxprom + %i5 = load i8, ptr %arrayidx, align 1 + store i8 %i5, ptr @vga_load_state_data, align 1 + %i6 = load i32, ptr %i, align 4 + %inc5 = add nsw i32 %i6, 1 + store i32 %inc5, ptr %i, align 4 + br label %for.cond1, !llvm.loop !0 +} + +attributes #0 = { "tune-cpu"="generic" } +attributes #1 = { nounwind } + +!0 = distinct !{!0, !1} +!1 = !{!"llvm.loop.mustprogress"} -- GitLab From 1fc3ce1cdb8390ed64feea939a9555d3642439ea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Valentin=20Clement=20=28=E3=83=90=E3=83=AC=E3=83=B3?= =?UTF-8?q?=E3=82=BF=E3=82=A4=E3=83=B3=20=E3=82=AF=E3=83=AC=E3=83=A1?= =?UTF-8?q?=E3=83=B3=29?= Date: Tue, 21 May 2024 11:23:55 -0700 Subject: [PATCH 021/452] [flang][cuda] Enable data transfer for descriptors (#92804) Remove the TODO when data transfer is done with descriptor variables. --- .../flang/Optimizer/Dialect/CUF/CUFOps.td | 10 ++++-- flang/lib/Lower/Bridge.cpp | 35 ++++++++++--------- flang/lib/Optimizer/Dialect/CUF/CUFOps.cpp | 13 +++++++ flang/test/Lower/CUDA/cuda-data-transfer.cuf | 19 ++++++++++ 4 files changed, 58 insertions(+), 19 deletions(-) diff --git a/flang/include/flang/Optimizer/Dialect/CUF/CUFOps.td b/flang/include/flang/Optimizer/Dialect/CUF/CUFOps.td index 1c98b4131a13..f2992997c42c 100644 --- a/flang/include/flang/Optimizer/Dialect/CUF/CUFOps.td +++ b/flang/include/flang/Optimizer/Dialect/CUF/CUFOps.td @@ -152,15 +152,21 @@ def cuf_DataTransferOp : cuf_Op<"data_transfer", []> { a = adev ! transfer device to host bdev = adev ! transfer device to device ``` + + When the data transfer is done on data hold by descriptors, the LHS data + hold by the descriptor are updated. When required, the LHS decriptor is also + updated. }]; - let arguments = (ins Arg:$src, - Arg:$dst, + let arguments = (ins Arg:$src, + Arg:$dst, cuf_DataTransferKindAttr:$transfer_kind); let assemblyFormat = [{ $src `to` $dst attr-dict `:` type(operands) }]; + + let hasVerifier = 1; } def cuf_KernelLaunchOp : cuf_Op<"kernel_launch", [CallOpInterface, diff --git a/flang/lib/Lower/Bridge.cpp b/flang/lib/Lower/Bridge.cpp index 4e50de3e7ee9..3e0a6da7fc32 100644 --- a/flang/lib/Lower/Bridge.cpp +++ b/flang/lib/Lower/Bridge.cpp @@ -3782,8 +3782,16 @@ private: hlfir::Entity &lhs, hlfir::Entity &rhs) { bool lhsIsDevice = Fortran::evaluate::HasCUDAAttrs(assign.lhs); bool rhsIsDevice = Fortran::evaluate::HasCUDAAttrs(assign.rhs); - if (rhs.isBoxAddressOrValue() || lhs.isBoxAddressOrValue()) - TODO(loc, "CUDA data transfler with descriptors"); + + auto getRefIfLoaded = [](mlir::Value val) -> mlir::Value { + if (auto loadOp = + mlir::dyn_cast_or_null(val.getDefiningOp())) + return loadOp.getMemref(); + return val; + }; + + mlir::Value rhsVal = getRefIfLoaded(rhs.getBase()); + mlir::Value lhsVal = getRefIfLoaded(lhs.getBase()); // device = host if (lhsIsDevice && !rhsIsDevice) { @@ -3792,11 +3800,12 @@ private: if (!rhs.isVariable()) { auto associate = hlfir::genAssociateExpr( loc, builder, rhs, rhs.getType(), ".cuf_host_tmp"); - builder.create(loc, associate.getBase(), lhs, + builder.create(loc, associate.getBase(), lhsVal, transferKindAttr); builder.create(loc, associate); } else { - builder.create(loc, rhs, lhs, transferKindAttr); + builder.create(loc, rhsVal, lhsVal, + transferKindAttr); } return; } @@ -3805,26 +3814,18 @@ private: if (!lhsIsDevice && rhsIsDevice) { auto transferKindAttr = cuf::DataTransferKindAttr::get( builder.getContext(), cuf::DataTransferKind::DeviceHost); - if (!rhs.isVariable()) { - // evaluateRhs loads scalar. Look for the memory reference to be used in - // the transfer. - if (mlir::isa_and_nonnull(rhs.getDefiningOp())) { - auto loadOp = mlir::dyn_cast(rhs.getDefiningOp()); - builder.create(loc, loadOp.getMemref(), lhs, - transferKindAttr); - return; - } - } else { - builder.create(loc, rhs, lhs, transferKindAttr); - } + builder.create(loc, rhsVal, lhsVal, + transferKindAttr); return; } + // device = device if (lhsIsDevice && rhsIsDevice) { assert(rhs.isVariable() && "CUDA Fortran assignment rhs is not legal"); auto transferKindAttr = cuf::DataTransferKindAttr::get( builder.getContext(), cuf::DataTransferKind::DeviceDevice); - builder.create(loc, rhs, lhs, transferKindAttr); + builder.create(loc, rhsVal, lhsVal, + transferKindAttr); return; } llvm_unreachable("Unhandled CUDA data transfer"); diff --git a/flang/lib/Optimizer/Dialect/CUF/CUFOps.cpp b/flang/lib/Optimizer/Dialect/CUF/CUFOps.cpp index 870652c72fab..b00c37468292 100644 --- a/flang/lib/Optimizer/Dialect/CUF/CUFOps.cpp +++ b/flang/lib/Optimizer/Dialect/CUF/CUFOps.cpp @@ -89,6 +89,19 @@ mlir::LogicalResult cuf::AllocateOp::verify() { return mlir::success(); } +//===----------------------------------------------------------------------===// +// DataTransferOp +//===----------------------------------------------------------------------===// + +mlir::LogicalResult cuf::DataTransferOp::verify() { + mlir::Type srcTy = getSrc().getType(); + mlir::Type dstTy = getDst().getType(); + if (fir::isa_ref_type(srcTy) && fir::isa_ref_type(dstTy) || + fir::isa_box_type(srcTy) && fir::isa_box_type(dstTy)) + return mlir::success(); + return emitOpError("expect src and dst to be both references or descriptors"); +} + //===----------------------------------------------------------------------===// // DeallocateOp //===----------------------------------------------------------------------===// diff --git a/flang/test/Lower/CUDA/cuda-data-transfer.cuf b/flang/test/Lower/CUDA/cuda-data-transfer.cuf index 084314ed63ec..e23792e6efc5 100644 --- a/flang/test/Lower/CUDA/cuda-data-transfer.cuf +++ b/flang/test/Lower/CUDA/cuda-data-transfer.cuf @@ -159,3 +159,22 @@ end subroutine ! CHECK-LABEL: func.func @_QPsub6 ! CHECK: cuf.data_transfer + +subroutine sub7(a, b, c) + integer, device, allocatable :: a(:), c(:) + integer, allocatable :: b(:) + b = a + + a = b + + c = a +end subroutine + +! CHECK-LABEL: func.func @_QPsub7( +! CHECK-SAME: %[[ARG0:.*]]: !fir.ref>>> {cuf.data_attr = #cuf.cuda, fir.bindc_name = "a"}, %[[ARG1:.*]]: !fir.ref>>> {fir.bindc_name = "b"}, %[[ARG2:.*]]: !fir.ref>>> {cuf.data_attr = #cuf.cuda, fir.bindc_name = "c"}) { +! CHECK: %[[A:.*]]:2 = hlfir.declare %[[ARG0]] dummy_scope %{{.*}} {data_attr = #cuf.cuda, fortran_attrs = #fir.var_attrs, uniq_name = "_QFsub7Ea"} : (!fir.ref>>>, !fir.dscope) -> (!fir.ref>>>, !fir.ref>>>) +! CHECK: %[[B:.*]]:2 = hlfir.declare %[[ARG1]] dummy_scope %{{.*}} {fortran_attrs = #fir.var_attrs, uniq_name = "_QFsub7Eb"} : (!fir.ref>>>, !fir.dscope) -> (!fir.ref>>>, !fir.ref>>>) +! CHECK: %[[C:.*]]:2 = hlfir.declare %[[ARG2]] dummy_scope %0 {data_attr = #cuf.cuda, fortran_attrs = #fir.var_attrs, uniq_name = "_QFsub7Ec"} : (!fir.ref>>>, !fir.dscope) -> (!fir.ref>>>, !fir.ref>>>) +! CHECK: cuf.data_transfer %[[A]]#0 to %[[B]]#0 {transfer_kind = #cuf.cuda_transfer} : !fir.ref>>>, !fir.ref>>> +! CHECK: cuf.data_transfer %[[B]]#0 to %[[A]]#0 {transfer_kind = #cuf.cuda_transfer} : !fir.ref>>>, !fir.ref>>> +! CHECK: cuf.data_transfer %[[A]]#0 to %[[C]]#0 {transfer_kind = #cuf.cuda_transfer} : !fir.ref>>>, !fir.ref>>> -- GitLab From 172759492a162592da7ae9e03888661c108b1be4 Mon Sep 17 00:00:00 2001 From: Matt Arsenault Date: Mon, 1 Apr 2024 09:02:40 +0300 Subject: [PATCH 022/452] RegisterPressure: Add parameter name comment --- llvm/lib/CodeGen/RegisterPressure.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/llvm/lib/CodeGen/RegisterPressure.cpp b/llvm/lib/CodeGen/RegisterPressure.cpp index 01042860ca9f..9a7eb49666b2 100644 --- a/llvm/lib/CodeGen/RegisterPressure.cpp +++ b/llvm/lib/CodeGen/RegisterPressure.cpp @@ -873,7 +873,7 @@ void RegPressureTracker::recede(SmallVectorImpl *LiveUses) { const MachineInstr &MI = *CurrPos; RegisterOperands RegOpers; - RegOpers.collect(MI, *TRI, *MRI, TrackLaneMasks, false); + RegOpers.collect(MI, *TRI, *MRI, TrackLaneMasks, /*IgnoreDead=*/false); if (TrackLaneMasks) { SlotIndex SlotIdx = LIS->getInstructionIndex(*CurrPos).getRegSlot(); RegOpers.adjustLaneLiveness(*LIS, *MRI, SlotIdx); @@ -1290,7 +1290,7 @@ void RegPressureTracker::bumpDownwardPressure(const MachineInstr *MI) { // Account for register pressure similar to RegPressureTracker::recede(). RegisterOperands RegOpers; - RegOpers.collect(*MI, *TRI, *MRI, TrackLaneMasks, false); + RegOpers.collect(*MI, *TRI, *MRI, TrackLaneMasks, /*IgnoreDead=*/false); if (TrackLaneMasks) RegOpers.adjustLaneLiveness(*LIS, *MRI, SlotIdx); -- GitLab From 7847b1ca00fb4649799125592f01cd38c5509b45 Mon Sep 17 00:00:00 2001 From: Valentin Clement Date: Tue, 21 May 2024 11:35:51 -0700 Subject: [PATCH 023/452] [flang][cuda][NFC] Silence warning triggered in buildbot --- flang/lib/Optimizer/Dialect/CUF/CUFOps.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/flang/lib/Optimizer/Dialect/CUF/CUFOps.cpp b/flang/lib/Optimizer/Dialect/CUF/CUFOps.cpp index b00c37468292..0446c1db86b1 100644 --- a/flang/lib/Optimizer/Dialect/CUF/CUFOps.cpp +++ b/flang/lib/Optimizer/Dialect/CUF/CUFOps.cpp @@ -96,8 +96,8 @@ mlir::LogicalResult cuf::AllocateOp::verify() { mlir::LogicalResult cuf::DataTransferOp::verify() { mlir::Type srcTy = getSrc().getType(); mlir::Type dstTy = getDst().getType(); - if (fir::isa_ref_type(srcTy) && fir::isa_ref_type(dstTy) || - fir::isa_box_type(srcTy) && fir::isa_box_type(dstTy)) + if ((fir::isa_ref_type(srcTy) && fir::isa_ref_type(dstTy)) || + (fir::isa_box_type(srcTy) && fir::isa_box_type(dstTy))) return mlir::success(); return emitOpError("expect src and dst to be both references or descriptors"); } -- GitLab From ce1d28e645b53ba9518d295dad35a4578dd8e8dc Mon Sep 17 00:00:00 2001 From: Aaron Ballman Date: Tue, 21 May 2024 14:46:42 -0400 Subject: [PATCH 024/452] Fix diagnostic wording style; NFC --- clang/include/clang/Basic/DiagnosticSemaKinds.td | 2 +- clang/test/Sema/builtins.c | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index c7dea1d54d06..d5973535edce 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -8853,7 +8853,7 @@ def err_atomic_exclusive_builtin_pointer_size : Error< "address argument to load or store exclusive builtin must be a pointer to" " 1,2,4 or 8 byte type (%0 invalid)">; def err_atomic_builtin_ext_int_size : Error< - "Atomic memory operand must have a power-of-two size">; + "atomic memory operand must have a power-of-two size">; def err_atomic_builtin_bit_int_prohibit : Error< "argument to atomic builtin of type '_BitInt' is not supported">; def err_atomic_op_needs_atomic : Error< diff --git a/clang/test/Sema/builtins.c b/clang/test/Sema/builtins.c index 3bee31459529..4f843aeec24e 100644 --- a/clang/test/Sema/builtins.c +++ b/clang/test/Sema/builtins.c @@ -277,9 +277,9 @@ void test21(const int *ptr) { } void test_ei_i42i(_BitInt(42) *ptr, int value) { - __sync_fetch_and_add(ptr, value); // expected-error {{Atomic memory operand must have a power-of-two size}} + __sync_fetch_and_add(ptr, value); // expected-error {{atomic memory operand must have a power-of-two size}} // expected-warning@+1 {{the semantics of this intrinsic changed with GCC version 4.4 - the newer semantics are provided here}} - __sync_nand_and_fetch(ptr, value); // expected-error {{Atomic memory operand must have a power-of-two size}} + __sync_nand_and_fetch(ptr, value); // expected-error {{atomic memory operand must have a power-of-two size}} __atomic_fetch_add(ptr, 1, 0); // expected-error {{argument to atomic builtin of type '_BitInt' is not supported}} } @@ -305,9 +305,9 @@ void test_ei_ii64(int *ptr, _BitInt(64) value) { } void test_ei_i42i42(_BitInt(42) *ptr, _BitInt(42) value) { - __sync_fetch_and_add(ptr, value); // expected-error {{Atomic memory operand must have a power-of-two size}} + __sync_fetch_and_add(ptr, value); // expected-error {{atomic memory operand must have a power-of-two size}} // expected-warning@+1 {{the semantics of this intrinsic changed with GCC version 4.4 - the newer semantics are provided here}} - __sync_nand_and_fetch(ptr, value); // expected-error {{Atomic memory operand must have a power-of-two size}} + __sync_nand_and_fetch(ptr, value); // expected-error {{atomic memory operand must have a power-of-two size}} } void test_ei_i64i64(_BitInt(64) *ptr, _BitInt(64) value) { -- GitLab From 8cb19ebd219668ef8efa9ffb4a72e39b18dd91d4 Mon Sep 17 00:00:00 2001 From: Matt Arsenault Date: Tue, 21 May 2024 20:49:21 +0200 Subject: [PATCH 025/452] InstCombine: Stop handling bitcast in PointerReplacer (#92937) These should be irrelevant since opaque pointers. --- .../InstCombine/InstCombineLoadStoreAlloca.cpp | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/llvm/lib/Transforms/InstCombine/InstCombineLoadStoreAlloca.cpp b/llvm/lib/Transforms/InstCombine/InstCombineLoadStoreAlloca.cpp index 4351a55ea1d3..832f89ed0b64 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineLoadStoreAlloca.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineLoadStoreAlloca.cpp @@ -332,7 +332,7 @@ bool PointerReplacer::collectUsersRecursive(Instruction &I) { Worklist.insert(SI); if (!collectUsersRecursive(*SI)) return false; - } else if (isa(Inst)) { + } else if (isa(Inst)) { Worklist.insert(Inst); if (!collectUsersRecursive(*Inst)) return false; @@ -393,15 +393,6 @@ void PointerReplacer::replace(Instruction *I) { NewI->takeName(GEP); NewI->setIsInBounds(GEP->isInBounds()); WorkMap[GEP] = NewI; - } else if (auto *BC = dyn_cast(I)) { - auto *V = getReplacement(BC->getOperand(0)); - assert(V && "Operand not replaced"); - auto *NewT = PointerType::get(BC->getType()->getContext(), - V->getType()->getPointerAddressSpace()); - auto *NewI = new BitCastInst(V, NewT); - IC.InsertNewInstWith(NewI, BC->getIterator()); - NewI->takeName(BC); - WorkMap[BC] = NewI; } else if (auto *SI = dyn_cast(I)) { auto *NewSI = SelectInst::Create( SI->getCondition(), getReplacement(SI->getTrueValue()), -- GitLab From 67ae86d700b899979db39883f4063257513498d5 Mon Sep 17 00:00:00 2001 From: lolloz98 Date: Tue, 21 May 2024 19:51:21 +0100 Subject: [PATCH 026/452] [clang] Fix crash passing function pointer without prototype. (#90255) Fixes use-after-free iterating over the uses of the function. Closes #88917 --- clang/lib/CodeGen/CodeGenModule.cpp | 21 ++++++++++++++------- clang/test/CodeGen/functions.c | 12 ++++++++++++ 2 files changed, 26 insertions(+), 7 deletions(-) diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp index 227813ad44e8..60ef28a0effa 100644 --- a/clang/lib/CodeGen/CodeGenModule.cpp +++ b/clang/lib/CodeGen/CodeGenModule.cpp @@ -5740,15 +5740,17 @@ CodeGenModule::getLLVMLinkageVarDefinition(const VarDecl *VD) { static void replaceUsesOfNonProtoConstant(llvm::Constant *old, llvm::Function *newFn) { // Fast path. - if (old->use_empty()) return; + if (old->use_empty()) + return; llvm::Type *newRetTy = newFn->getReturnType(); - SmallVector newArgs; + SmallVector newArgs; + + SmallVector callSitesToBeRemovedFromParent; for (llvm::Value::use_iterator ui = old->use_begin(), ue = old->use_end(); - ui != ue; ) { - llvm::Value::use_iterator use = ui++; // Increment before the use is erased. - llvm::User *user = use->getUser(); + ui != ue; ui++) { + llvm::User *user = ui->getUser(); // Recognize and replace uses of bitcasts. Most calls to // unprototyped functions will use bitcasts. @@ -5760,8 +5762,9 @@ static void replaceUsesOfNonProtoConstant(llvm::Constant *old, // Recognize calls to the function. llvm::CallBase *callSite = dyn_cast(user); - if (!callSite) continue; - if (!callSite->isCallee(&*use)) + if (!callSite) + continue; + if (!callSite->isCallee(&*ui)) continue; // If the return types don't match exactly, then we can't @@ -5830,6 +5833,10 @@ static void replaceUsesOfNonProtoConstant(llvm::Constant *old, if (callSite->getDebugLoc()) newCall->setDebugLoc(callSite->getDebugLoc()); + callSitesToBeRemovedFromParent.push_back(callSite); + } + + for (auto *callSite : callSitesToBeRemovedFromParent) { callSite->eraseFromParent(); } } diff --git a/clang/test/CodeGen/functions.c b/clang/test/CodeGen/functions.c index 1bbaa80d653c..0cc999aa4916 100644 --- a/clang/test/CodeGen/functions.c +++ b/clang/test/CodeGen/functions.c @@ -61,3 +61,15 @@ static void test9_helper(void) {} void test9(void) { (void) test9_helper; } + +// PR88917: don't crash +int b(); + +int main() { + return b(b); + // CHECK: call i32 @b(ptr noundef @b) +} +int b(int (*f)()){ + return 0; +} +// CHECK-LABEL: define{{.*}} i32 @b(ptr noundef %f) -- GitLab From e67f2cc3fc38cec2041cfb197ac4688ed3d16e7e Mon Sep 17 00:00:00 2001 From: Edwin Vane Date: Tue, 21 May 2024 14:51:50 -0400 Subject: [PATCH 027/452] [clang-tidy] Rename out-of-line function definitions (#91954) Member function templates defined out-of-line were resulting in conflicting naming failures with overlapping usage sets. With this change, out-of-line definitions are treated as a usage of the failure which is the inline declaration. --- .../utils/RenamerClangTidyCheck.cpp | 3 ++ clang-tools-extra/docs/ReleaseNotes.rst | 3 +- .../identifier-naming-outofline.cpp | 30 +++++++++++++++++++ 3 files changed, 35 insertions(+), 1 deletion(-) create mode 100644 clang-tools-extra/test/clang-tidy/checkers/readability/identifier-naming-outofline.cpp diff --git a/clang-tools-extra/clang-tidy/utils/RenamerClangTidyCheck.cpp b/clang-tools-extra/clang-tidy/utils/RenamerClangTidyCheck.cpp index e811f5519de2..88e4886cd0df 100644 --- a/clang-tools-extra/clang-tidy/utils/RenamerClangTidyCheck.cpp +++ b/clang-tools-extra/clang-tidy/utils/RenamerClangTidyCheck.cpp @@ -123,6 +123,9 @@ static const NamedDecl *getFailureForNamedDecl(const NamedDecl *ND) { if (const auto *Method = dyn_cast(ND)) { if (const CXXMethodDecl *Overridden = getOverrideMethod(Method)) Canonical = cast(Overridden->getCanonicalDecl()); + else if (const FunctionTemplateDecl *Primary = Method->getPrimaryTemplate()) + if (const FunctionDecl *TemplatedDecl = Primary->getTemplatedDecl()) + Canonical = cast(TemplatedDecl->getCanonicalDecl()); if (Canonical != ND) return Canonical; diff --git a/clang-tools-extra/docs/ReleaseNotes.rst b/clang-tools-extra/docs/ReleaseNotes.rst index 6a9892bada91..741abc0a199a 100644 --- a/clang-tools-extra/docs/ReleaseNotes.rst +++ b/clang-tools-extra/docs/ReleaseNotes.rst @@ -375,7 +375,8 @@ Changes in existing checks ` check in `GetConfigPerFile` mode by resolving symbolic links to header files. Fixed handling of Hungarian Prefix when configured to `LowerCase`. Added support for renaming designated - initializers. Added support for renaming macro arguments. + initializers. Added support for renaming macro arguments. Fixed renaming + conflicts arising from out-of-line member function template definitions. - Improved :doc:`readability-implicit-bool-conversion ` check to provide diff --git a/clang-tools-extra/test/clang-tidy/checkers/readability/identifier-naming-outofline.cpp b/clang-tools-extra/test/clang-tidy/checkers/readability/identifier-naming-outofline.cpp new file mode 100644 index 000000000000..f807875e2769 --- /dev/null +++ b/clang-tools-extra/test/clang-tidy/checkers/readability/identifier-naming-outofline.cpp @@ -0,0 +1,30 @@ +// RUN: %check_clang_tidy %s readability-identifier-naming %t -std=c++20 \ +// RUN: --config='{CheckOptions: { \ +// RUN: readability-identifier-naming.MethodCase: CamelCase, \ +// RUN: }}' + +namespace SomeNamespace { +namespace Inner { + +class SomeClass { +public: + template + int someMethod(); +// CHECK-MESSAGES: :[[@LINE-1]]:9: warning: invalid case style for method 'someMethod' [readability-identifier-naming] +// CHECK-FIXES: {{^}} int SomeMethod(); +}; +template +int SomeClass::someMethod() { +// CHECK-FIXES: {{^}}int SomeClass::SomeMethod() { + return 5; +} + +} // namespace Inner + +void someFunc() { + Inner::SomeClass S; + S.someMethod(); +// CHECK-FIXES: {{^}} S.SomeMethod(); +} + +} // namespace SomeNamespace -- GitLab From cec1eab9bd6bfffcf39d0962c7ce220284fc7c1a Mon Sep 17 00:00:00 2001 From: Matt Arsenault Date: Mon, 1 Apr 2024 16:38:51 +0300 Subject: [PATCH 028/452] MachineScheduler: Add parameter name comments --- llvm/lib/CodeGen/MachineScheduler.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/llvm/lib/CodeGen/MachineScheduler.cpp b/llvm/lib/CodeGen/MachineScheduler.cpp index 78d581c8cead..0858be64de40 100644 --- a/llvm/lib/CodeGen/MachineScheduler.cpp +++ b/llvm/lib/CodeGen/MachineScheduler.cpp @@ -1664,7 +1664,8 @@ void ScheduleDAGMILive::scheduleMI(SUnit *SU, bool IsTopNode) { if (ShouldTrackPressure) { // Update top scheduled pressure. RegisterOperands RegOpers; - RegOpers.collect(*MI, *TRI, MRI, ShouldTrackLaneMasks, false); + RegOpers.collect(*MI, *TRI, MRI, ShouldTrackLaneMasks, + /*IgnoreDead=*/false); if (ShouldTrackLaneMasks) { // Adjust liveness and add missing dead+read-undef flags. SlotIndex SlotIdx = LIS->getInstructionIndex(*MI).getRegSlot(); @@ -1698,7 +1699,8 @@ void ScheduleDAGMILive::scheduleMI(SUnit *SU, bool IsTopNode) { } if (ShouldTrackPressure) { RegisterOperands RegOpers; - RegOpers.collect(*MI, *TRI, MRI, ShouldTrackLaneMasks, false); + RegOpers.collect(*MI, *TRI, MRI, ShouldTrackLaneMasks, + /*IgnoreDead=*/false); if (ShouldTrackLaneMasks) { // Adjust liveness and add missing dead+read-undef flags. SlotIndex SlotIdx = LIS->getInstructionIndex(*MI).getRegSlot(); -- GitLab From 01c600dec6f506ae305abf04cf955e08aa59b234 Mon Sep 17 00:00:00 2001 From: Aaron Ballman Date: Tue, 21 May 2024 15:00:40 -0400 Subject: [PATCH 029/452] Reword a diagnostic for style; NFC --- .../clang/Basic/DiagnosticSemaKinds.td | 2 +- clang/test/Parser/altivec.c | 24 +++++++++---------- clang/test/Parser/cxx-altivec.cpp | 24 +++++++++---------- 3 files changed, 25 insertions(+), 25 deletions(-) diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index d5973535edce..b2e9bed52220 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -310,7 +310,7 @@ def err_invalid_vector_long_double_decl_spec : Error< def err_invalid_vector_complex_decl_spec : Error< "cannot use '_Complex' with '__vector'">; def warn_vector_long_decl_spec_combination : Warning< - "Use of 'long' with '__vector' is deprecated">, InGroup; + "use of 'long' with '__vector' is deprecated">, InGroup; def err_redeclaration_different_type : Error< "redeclaration of %0 with a different type%diff{: $ vs $|}1,2">; diff --git a/clang/test/Parser/altivec.c b/clang/test/Parser/altivec.c index 445369f0dc06..9291b9b69160 100644 --- a/clang/test/Parser/altivec.c +++ b/clang/test/Parser/altivec.c @@ -56,40 +56,40 @@ void f_a2(int b, vector int a); vector int v = (vector int)(-1); // These should have errors on AIX and warnings otherwise. -__vector long vv_l; // nonaix-warning {{Use of 'long' with '__vector' is deprecated}} +__vector long vv_l; // nonaix-warning {{use of 'long' with '__vector' is deprecated}} // aix-error@-1 {{cannot use 'long' with '__vector'}} // novsx-error@-2 {{cannot use 'long' with '__vector'}} -__vector signed long vv_sl; // nonaix-warning {{Use of 'long' with '__vector' is deprecated}} +__vector signed long vv_sl; // nonaix-warning {{use of 'long' with '__vector' is deprecated}} // aix-error@-1 {{cannot use 'long' with '__vector'}} // novsx-error@-2 {{cannot use 'long' with '__vector'}} -__vector unsigned long vv_ul; // nonaix-warning {{Use of 'long' with '__vector' is deprecated}} +__vector unsigned long vv_ul; // nonaix-warning {{use of 'long' with '__vector' is deprecated}} // aix-error@-1 {{cannot use 'long' with '__vector'}} // novsx-error@-2 {{cannot use 'long' with '__vector'}} -__vector long int vv_li; // nonaix-warning {{Use of 'long' with '__vector' is deprecated}} +__vector long int vv_li; // nonaix-warning {{use of 'long' with '__vector' is deprecated}} // aix-error@-1 {{cannot use 'long' with '__vector'}} // novsx-error@-2 {{cannot use 'long' with '__vector'}} -__vector signed long int vv_sli; // nonaix-warning {{Use of 'long' with '__vector' is deprecated}} +__vector signed long int vv_sli; // nonaix-warning {{use of 'long' with '__vector' is deprecated}} // aix-error@-1 {{cannot use 'long' with '__vector'}} // novsx-error@-2 {{cannot use 'long' with '__vector'}} -__vector unsigned long int vv_uli; // nonaix-warning {{Use of 'long' with '__vector' is deprecated}} +__vector unsigned long int vv_uli; // nonaix-warning {{use of 'long' with '__vector' is deprecated}} // aix-error@-1 {{cannot use 'long' with '__vector'}} // novsx-error@-2 {{cannot use 'long' with '__vector'}} -vector long v_l; // nonaix-warning {{Use of 'long' with '__vector' is deprecated}} +vector long v_l; // nonaix-warning {{use of 'long' with '__vector' is deprecated}} // aix-error@-1 {{cannot use 'long' with '__vector'}} // novsx-error@-2 {{cannot use 'long' with '__vector'}} -vector signed long v_sl; // nonaix-warning {{Use of 'long' with '__vector' is deprecated}} +vector signed long v_sl; // nonaix-warning {{use of 'long' with '__vector' is deprecated}} // aix-error@-1 {{cannot use 'long' with '__vector'}} // novsx-error@-2 {{cannot use 'long' with '__vector'}} -vector unsigned long v_ul; // nonaix-warning {{Use of 'long' with '__vector' is deprecated}} +vector unsigned long v_ul; // nonaix-warning {{use of 'long' with '__vector' is deprecated}} // aix-error@-1 {{cannot use 'long' with '__vector'}} // novsx-error@-2 {{cannot use 'long' with '__vector'}} -vector long int v_li; // nonaix-warning {{Use of 'long' with '__vector' is deprecated}} +vector long int v_li; // nonaix-warning {{use of 'long' with '__vector' is deprecated}} // aix-error@-1 {{cannot use 'long' with '__vector'}} // novsx-error@-2 {{cannot use 'long' with '__vector'}} -vector signed long int v_sli; // nonaix-warning {{Use of 'long' with '__vector' is deprecated}} +vector signed long int v_sli; // nonaix-warning {{use of 'long' with '__vector' is deprecated}} // aix-error@-1 {{cannot use 'long' with '__vector'}} // novsx-error@-2 {{cannot use 'long' with '__vector'}} -vector unsigned long int v_uli; // nonaix-warning {{Use of 'long' with '__vector' is deprecated}} +vector unsigned long int v_uli; // nonaix-warning {{use of 'long' with '__vector' is deprecated}} // aix-error@-1 {{cannot use 'long' with '__vector'}} // novsx-error@-2 {{cannot use 'long' with '__vector'}} diff --git a/clang/test/Parser/cxx-altivec.cpp b/clang/test/Parser/cxx-altivec.cpp index 5cb760dababb..15a6bf6d1be8 100644 --- a/clang/test/Parser/cxx-altivec.cpp +++ b/clang/test/Parser/cxx-altivec.cpp @@ -59,40 +59,40 @@ void f_a2(int b, vector int a); vector int v = (vector int)(-1); // These should have errors on AIX and warnings otherwise. -__vector long vv_l; // nonaix-warning {{Use of 'long' with '__vector' is deprecated}} +__vector long vv_l; // nonaix-warning {{use of 'long' with '__vector' is deprecated}} // aix-error@-1 {{cannot use 'long' with '__vector'}} // novsx-error@-2 {{cannot use 'long' with '__vector'}} -__vector signed long vv_sl; // nonaix-warning {{Use of 'long' with '__vector' is deprecated}} +__vector signed long vv_sl; // nonaix-warning {{use of 'long' with '__vector' is deprecated}} // aix-error@-1 {{cannot use 'long' with '__vector'}} // novsx-error@-2 {{cannot use 'long' with '__vector'}} -__vector unsigned long vv_ul; // nonaix-warning {{Use of 'long' with '__vector' is deprecated}} +__vector unsigned long vv_ul; // nonaix-warning {{use of 'long' with '__vector' is deprecated}} // aix-error@-1 {{cannot use 'long' with '__vector'}} // novsx-error@-2 {{cannot use 'long' with '__vector'}} -__vector long int vv_li; // nonaix-warning {{Use of 'long' with '__vector' is deprecated}} +__vector long int vv_li; // nonaix-warning {{use of 'long' with '__vector' is deprecated}} // aix-error@-1 {{cannot use 'long' with '__vector'}} // novsx-error@-2 {{cannot use 'long' with '__vector'}} -__vector signed long int vv_sli; // nonaix-warning {{Use of 'long' with '__vector' is deprecated}} +__vector signed long int vv_sli; // nonaix-warning {{use of 'long' with '__vector' is deprecated}} // aix-error@-1 {{cannot use 'long' with '__vector'}} // novsx-error@-2 {{cannot use 'long' with '__vector'}} -__vector unsigned long int vv_uli; // nonaix-warning {{Use of 'long' with '__vector' is deprecated}} +__vector unsigned long int vv_uli; // nonaix-warning {{use of 'long' with '__vector' is deprecated}} // aix-error@-1 {{cannot use 'long' with '__vector'}} // novsx-error@-2 {{cannot use 'long' with '__vector'}} -vector long v_l; // nonaix-warning {{Use of 'long' with '__vector' is deprecated}} +vector long v_l; // nonaix-warning {{use of 'long' with '__vector' is deprecated}} // aix-error@-1 {{cannot use 'long' with '__vector'}} // novsx-error@-2 {{cannot use 'long' with '__vector'}} -vector signed long v_sl; // nonaix-warning {{Use of 'long' with '__vector' is deprecated}} +vector signed long v_sl; // nonaix-warning {{use of 'long' with '__vector' is deprecated}} // aix-error@-1 {{cannot use 'long' with '__vector'}} // novsx-error@-2 {{cannot use 'long' with '__vector'}} -vector unsigned long v_ul; // nonaix-warning {{Use of 'long' with '__vector' is deprecated}} +vector unsigned long v_ul; // nonaix-warning {{use of 'long' with '__vector' is deprecated}} // aix-error@-1 {{cannot use 'long' with '__vector'}} // novsx-error@-2 {{cannot use 'long' with '__vector'}} -vector long int v_li; // nonaix-warning {{Use of 'long' with '__vector' is deprecated}} +vector long int v_li; // nonaix-warning {{use of 'long' with '__vector' is deprecated}} // aix-error@-1 {{cannot use 'long' with '__vector'}} // novsx-error@-2 {{cannot use 'long' with '__vector'}} -vector signed long int v_sli; // nonaix-warning {{Use of 'long' with '__vector' is deprecated}} +vector signed long int v_sli; // nonaix-warning {{use of 'long' with '__vector' is deprecated}} // aix-error@-1 {{cannot use 'long' with '__vector'}} // novsx-error@-2 {{cannot use 'long' with '__vector'}} -vector unsigned long int v_uli; // nonaix-warning {{Use of 'long' with '__vector' is deprecated}} +vector unsigned long int v_uli; // nonaix-warning {{use of 'long' with '__vector' is deprecated}} // aix-error@-1 {{cannot use 'long' with '__vector'}} // novsx-error@-2 {{cannot use 'long' with '__vector'}} -- GitLab From 32cf7a25f2f8174bc448ae7032e419dc0375fd6a Mon Sep 17 00:00:00 2001 From: Aaron Ballman Date: Tue, 21 May 2024 15:03:26 -0400 Subject: [PATCH 030/452] Fix another diagnostic for style; NFC --- clang/include/clang/Basic/DiagnosticSemaKinds.td | 2 +- clang/test/SemaCXX/warn-thread-safety-analysis.cpp | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index b2e9bed52220..f6e632ba53a9 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -3975,7 +3975,7 @@ def warn_acquired_before : Warning< "%0 '%1' must be acquired before '%2'">, InGroup, DefaultIgnore; def warn_acquired_before_after_cycle : Warning< - "Cycle in acquired_before/after dependencies, starting with '%0'">, + "cycle in acquired_before/after dependencies, starting with '%0'">, InGroup, DefaultIgnore; diff --git a/clang/test/SemaCXX/warn-thread-safety-analysis.cpp b/clang/test/SemaCXX/warn-thread-safety-analysis.cpp index 749d9e135d94..73cc946ca0ce 100644 --- a/clang/test/SemaCXX/warn-thread-safety-analysis.cpp +++ b/clang/test/SemaCXX/warn-thread-safety-analysis.cpp @@ -5838,12 +5838,12 @@ class Foo5 { class Foo6 { - Mutex mu1 ACQUIRED_AFTER(mu3); // expected-warning {{Cycle in acquired_before/after dependencies, starting with 'mu1'}} - Mutex mu2 ACQUIRED_AFTER(mu1); // expected-warning {{Cycle in acquired_before/after dependencies, starting with 'mu2'}} - Mutex mu3 ACQUIRED_AFTER(mu2); // expected-warning {{Cycle in acquired_before/after dependencies, starting with 'mu3'}} + Mutex mu1 ACQUIRED_AFTER(mu3); // expected-warning {{cycle in acquired_before/after dependencies, starting with 'mu1'}} + Mutex mu2 ACQUIRED_AFTER(mu1); // expected-warning {{cycle in acquired_before/after dependencies, starting with 'mu2'}} + Mutex mu3 ACQUIRED_AFTER(mu2); // expected-warning {{cycle in acquired_before/after dependencies, starting with 'mu3'}} - Mutex mu_b ACQUIRED_BEFORE(mu_b); // expected-warning {{Cycle in acquired_before/after dependencies, starting with 'mu_b'}} - Mutex mu_a ACQUIRED_AFTER(mu_a); // expected-warning {{Cycle in acquired_before/after dependencies, starting with 'mu_a'}} + Mutex mu_b ACQUIRED_BEFORE(mu_b); // expected-warning {{cycle in acquired_before/after dependencies, starting with 'mu_b'}} + Mutex mu_a ACQUIRED_AFTER(mu_a); // expected-warning {{cycle in acquired_before/after dependencies, starting with 'mu_a'}} void test0() { mu_a.Lock(); -- GitLab From 87a6865d2c8eba802a7e9f42fa8b6ac1edd0664e Mon Sep 17 00:00:00 2001 From: Aaron Ballman Date: Tue, 21 May 2024 15:14:03 -0400 Subject: [PATCH 031/452] Fix another diagnostic wording for style; NFC --- .../clang/Basic/DiagnosticSemaKinds.td | 6 +-- clang/test/Parser/lax-conv.cpp | 52 +++++++++---------- 2 files changed, 29 insertions(+), 29 deletions(-) diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index f6e632ba53a9..5a32463763aa 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -8003,9 +8003,9 @@ def warn_deprecated_altivec_src_compat : Warning< InGroup>; def warn_deprecated_lax_vec_conv_all : Warning< - "Implicit conversion between vector types ('%0' and '%1') is deprecated. " - "In the future, the behavior implied by '-fno-lax-vector-conversions' " - "will be the default.">, + "implicit conversion between vector types ('%0' and '%1') is deprecated; " + "in the future, the behavior implied by '-fno-lax-vector-conversions' " + "will be the default">, InGroup>; def err_catch_incomplete_ptr : Error< diff --git a/clang/test/Parser/lax-conv.cpp b/clang/test/Parser/lax-conv.cpp index f784e3fa74e7..0cb2503a9691 100644 --- a/clang/test/Parser/lax-conv.cpp +++ b/clang/test/Parser/lax-conv.cpp @@ -21,10 +21,10 @@ template VEC __attribute__((noinline)) test(vector unsigned char return (VEC)(a * b); } vector unsigned int test1(vector unsigned char RetImplicitConv) { - return RetImplicitConv; // expected-warning {{Implicit conversion between vector types (''__vector unsigned char' (vector of 16 'unsigned char' values)' and ''__vector unsigned int' (vector of 4 'unsigned int' values)') is deprecated. In the future, the behavior implied by '-fno-lax-vector-conversions' will be the default.}} + return RetImplicitConv; // expected-warning {{implicit conversion between vector types (''__vector unsigned char' (vector of 16 'unsigned char' values)' and ''__vector unsigned int' (vector of 4 'unsigned int' values)') is deprecated; in the future, the behavior implied by '-fno-lax-vector-conversions' will be the default}} } vector unsigned int test2(vector unsigned char RetImplicitConvAddConst) { - return RetImplicitConvAddConst + 5; // expected-warning {{Implicit conversion between vector types (''__vector unsigned char' (vector of 16 'unsigned char' values)' and ''__vector unsigned int' (vector of 4 'unsigned int' values)') is deprecated. In the future, the behavior implied by '-fno-lax-vector-conversions' will be the default.}} + return RetImplicitConvAddConst + 5; // expected-warning {{implicit conversion between vector types (''__vector unsigned char' (vector of 16 'unsigned char' values)' and ''__vector unsigned int' (vector of 4 'unsigned int' values)') is deprecated; in the future, the behavior implied by '-fno-lax-vector-conversions' will be the default}} } vector unsigned int test3(vector unsigned char RetExplicitConv) { return (vector unsigned int)RetExplicitConv; @@ -34,7 +34,7 @@ vector unsigned int test4(vector unsigned char RetExplicitConvAddConst) { } vector unsigned int test5(vector unsigned char RetImplicitConvAddSame1, vector unsigned char RetImplicitConvAddSame2) { - return RetImplicitConvAddSame1 + RetImplicitConvAddSame2; // expected-warning {{Implicit conversion between vector types (''__vector unsigned char' (vector of 16 'unsigned char' values)' and ''__vector unsigned int' (vector of 4 'unsigned int' values)') is deprecated. In the future, the behavior implied by '-fno-lax-vector-conversions' will be the default.}} + return RetImplicitConvAddSame1 + RetImplicitConvAddSame2; // expected-warning {{implicit conversion between vector types (''__vector unsigned char' (vector of 16 'unsigned char' values)' and ''__vector unsigned int' (vector of 4 'unsigned int' values)') is deprecated; in the future, the behavior implied by '-fno-lax-vector-conversions' will be the default}} } vector unsigned int test6(vector unsigned char RetExplicitConvAddSame1, vector unsigned char RetExplicitConvAddSame2) { @@ -54,10 +54,10 @@ vector unsigned long long test9(vector unsigned char a, vector unsigned char b) return test(a, b); } void test1a(vector unsigned char ArgImplicitConv) { - return dummy(ArgImplicitConv); // expected-warning {{Implicit conversion between vector types (''__vector unsigned char' (vector of 16 'unsigned char' values)' and ''__vector unsigned int' (vector of 4 'unsigned int' values)') is deprecated. In the future, the behavior implied by '-fno-lax-vector-conversions' will be the default.}} + return dummy(ArgImplicitConv); // expected-warning {{implicit conversion between vector types (''__vector unsigned char' (vector of 16 'unsigned char' values)' and ''__vector unsigned int' (vector of 4 'unsigned int' values)') is deprecated; in the future, the behavior implied by '-fno-lax-vector-conversions' will be the default}} } void test2a(vector unsigned char ArgImplicitConvAddConst) { - return dummy(ArgImplicitConvAddConst + 5); // expected-warning {{Implicit conversion between vector types (''__vector unsigned char' (vector of 16 'unsigned char' values)' and ''__vector unsigned int' (vector of 4 'unsigned int' values)') is deprecated. In the future, the behavior implied by '-fno-lax-vector-conversions' will be the default.}} + return dummy(ArgImplicitConvAddConst + 5); // expected-warning {{implicit conversion between vector types (''__vector unsigned char' (vector of 16 'unsigned char' values)' and ''__vector unsigned int' (vector of 4 'unsigned int' values)') is deprecated; in the future, the behavior implied by '-fno-lax-vector-conversions' will be the default}} } void test3a(vector unsigned char ArgExplicitConv) { return dummy((vector unsigned int)ArgExplicitConv); @@ -67,7 +67,7 @@ void test4a(vector unsigned char ArgExplicitConvAddConst) { } void test5a(vector unsigned char ArgImplicitConvAddSame1, vector unsigned char ArgImplicitConvAddSame2) { - return dummy(ArgImplicitConvAddSame1 + ArgImplicitConvAddSame2); // expected-warning {{Implicit conversion between vector types (''__vector unsigned char' (vector of 16 'unsigned char' values)' and ''__vector unsigned int' (vector of 4 'unsigned int' values)') is deprecated. In the future, the behavior implied by '-fno-lax-vector-conversions' will be the default.}} + return dummy(ArgImplicitConvAddSame1 + ArgImplicitConvAddSame2); // expected-warning {{implicit conversion between vector types (''__vector unsigned char' (vector of 16 'unsigned char' values)' and ''__vector unsigned int' (vector of 4 'unsigned int' values)') is deprecated; in the future, the behavior implied by '-fno-lax-vector-conversions' will be the default}} } void test6a(vector unsigned char ArgExplicitConvAddSame1, vector unsigned char ArgExplicitConvAddSame2) { @@ -80,33 +80,33 @@ void test7a(vector unsigned char ArgExplicitConvAddSame1Full, ArgExplicitConvAddSame2Full)); } void test_bool_compat(void) { - vbs = vss; // expected-warning {{Implicit conversion between vector types (''__vector short' (vector of 8 'short' values)' and ''__vector __bool unsigned short' (vector of 8 'unsigned short' values)') is deprecated. In the future, the behavior implied by '-fno-lax-vector-conversions' will be the default.}} - vbs = vus; // expected-warning {{Implicit conversion between vector types (''__vector unsigned short' (vector of 8 'unsigned short' values)' and ''__vector __bool unsigned short' (vector of 8 'unsigned short' values)') is deprecated. In the future, the behavior implied by '-fno-lax-vector-conversions' will be the default.}} + vbs = vss; // expected-warning {{implicit conversion between vector types (''__vector short' (vector of 8 'short' values)' and ''__vector __bool unsigned short' (vector of 8 'unsigned short' values)') is deprecated; in the future, the behavior implied by '-fno-lax-vector-conversions' will be the default}} + vbs = vus; // expected-warning {{implicit conversion between vector types (''__vector unsigned short' (vector of 8 'unsigned short' values)' and ''__vector __bool unsigned short' (vector of 8 'unsigned short' values)') is deprecated; in the future, the behavior implied by '-fno-lax-vector-conversions' will be the default}} - vbi = vsi; // expected-warning {{Implicit conversion between vector types (''__vector int' (vector of 4 'int' values)' and ''__vector __bool unsigned int' (vector of 4 'unsigned int' values)') is deprecated. In the future, the behavior implied by '-fno-lax-vector-conversions' will be the default.}} - vbi = vui; // expected-warning {{Implicit conversion between vector types (''__vector unsigned int' (vector of 4 'unsigned int' values)' and ''__vector __bool unsigned int' (vector of 4 'unsigned int' values)') is deprecated. In the future, the behavior implied by '-fno-lax-vector-conversions' will be the default.}} + vbi = vsi; // expected-warning {{implicit conversion between vector types (''__vector int' (vector of 4 'int' values)' and ''__vector __bool unsigned int' (vector of 4 'unsigned int' values)') is deprecated; in the future, the behavior implied by '-fno-lax-vector-conversions' will be the default}} + vbi = vui; // expected-warning {{implicit conversion between vector types (''__vector unsigned int' (vector of 4 'unsigned int' values)' and ''__vector __bool unsigned int' (vector of 4 'unsigned int' values)') is deprecated; in the future, the behavior implied by '-fno-lax-vector-conversions' will be the default}} - vbl = vsl; // expected-warning {{Implicit conversion between vector types (''__vector long long' (vector of 2 'long long' values)' and ''__vector __bool unsigned long long' (vector of 2 'unsigned long long' values)') is deprecated. In the future, the behavior implied by '-fno-lax-vector-conversions' will be the default.}} - vbl = vul; // expected-warning {{Implicit conversion between vector types (''__vector unsigned long long' (vector of 2 'unsigned long long' values)' and ''__vector __bool unsigned long long' (vector of 2 'unsigned long long' values)') is deprecated. In the future, the behavior implied by '-fno-lax-vector-conversions' will be the default.}} + vbl = vsl; // expected-warning {{implicit conversion between vector types (''__vector long long' (vector of 2 'long long' values)' and ''__vector __bool unsigned long long' (vector of 2 'unsigned long long' values)') is deprecated; in the future, the behavior implied by '-fno-lax-vector-conversions' will be the default}} + vbl = vul; // expected-warning {{implicit conversion between vector types (''__vector unsigned long long' (vector of 2 'unsigned long long' values)' and ''__vector __bool unsigned long long' (vector of 2 'unsigned long long' values)') is deprecated; in the future, the behavior implied by '-fno-lax-vector-conversions' will be the default}} - vbc = vsc; // expected-warning {{Implicit conversion between vector types (''__vector signed char' (vector of 16 'signed char' values)' and ''__vector __bool unsigned char' (vector of 16 'unsigned char' values)') is deprecated. In the future, the behavior implied by '-fno-lax-vector-conversions' will be the default.}} - vbc = vuc; // expected-warning {{Implicit conversion between vector types (''__vector unsigned char' (vector of 16 'unsigned char' values)' and ''__vector __bool unsigned char' (vector of 16 'unsigned char' values)') is deprecated. In the future, the behavior implied by '-fno-lax-vector-conversions' will be the default.}} + vbc = vsc; // expected-warning {{implicit conversion between vector types (''__vector signed char' (vector of 16 'signed char' values)' and ''__vector __bool unsigned char' (vector of 16 'unsigned char' values)') is deprecated; in the future, the behavior implied by '-fno-lax-vector-conversions' will be the default}} + vbc = vuc; // expected-warning {{implicit conversion between vector types (''__vector unsigned char' (vector of 16 'unsigned char' values)' and ''__vector __bool unsigned char' (vector of 16 'unsigned char' values)') is deprecated; in the future, the behavior implied by '-fno-lax-vector-conversions' will be the default}} } void test_pixel_compat(void) { - vp = vbs; // expected-warning {{Implicit conversion between vector types (''__vector __bool unsigned short' (vector of 8 'unsigned short' values)' and ''__vector __pixel ' (vector of 8 'unsigned short' values)') is deprecated. In the future, the behavior implied by '-fno-lax-vector-conversions' will be the default.}} - vp = vss; // expected-warning {{Implicit conversion between vector types (''__vector short' (vector of 8 'short' values)' and ''__vector __pixel ' (vector of 8 'unsigned short' values)') is deprecated. In the future, the behavior implied by '-fno-lax-vector-conversions' will be the default.}} - vp = vus; // expected-warning {{Implicit conversion between vector types (''__vector unsigned short' (vector of 8 'unsigned short' values)' and ''__vector __pixel ' (vector of 8 'unsigned short' values)') is deprecated. In the future, the behavior implied by '-fno-lax-vector-conversions' will be the default.}} + vp = vbs; // expected-warning {{implicit conversion between vector types (''__vector __bool unsigned short' (vector of 8 'unsigned short' values)' and ''__vector __pixel ' (vector of 8 'unsigned short' values)') is deprecated; in the future, the behavior implied by '-fno-lax-vector-conversions' will be the default}} + vp = vss; // expected-warning {{implicit conversion between vector types (''__vector short' (vector of 8 'short' values)' and ''__vector __pixel ' (vector of 8 'unsigned short' values)') is deprecated; in the future, the behavior implied by '-fno-lax-vector-conversions' will be the default}} + vp = vus; // expected-warning {{implicit conversion between vector types (''__vector unsigned short' (vector of 8 'unsigned short' values)' and ''__vector __pixel ' (vector of 8 'unsigned short' values)') is deprecated; in the future, the behavior implied by '-fno-lax-vector-conversions' will be the default}} - vp = vbi; // expected-warning {{Implicit conversion between vector types (''__vector __bool unsigned int' (vector of 4 'unsigned int' values)' and ''__vector __pixel ' (vector of 8 'unsigned short' values)') is deprecated. In the future, the behavior implied by '-fno-lax-vector-conversions' will be the default.}} - vp = vsi; // expected-warning {{Implicit conversion between vector types (''__vector int' (vector of 4 'int' values)' and ''__vector __pixel ' (vector of 8 'unsigned short' values)') is deprecated. In the future, the behavior implied by '-fno-lax-vector-conversions' will be the default.}} - vp = vui; // expected-warning {{Implicit conversion between vector types (''__vector unsigned int' (vector of 4 'unsigned int' values)' and ''__vector __pixel ' (vector of 8 'unsigned short' values)') is deprecated. In the future, the behavior implied by '-fno-lax-vector-conversions' will be the default.}} + vp = vbi; // expected-warning {{implicit conversion between vector types (''__vector __bool unsigned int' (vector of 4 'unsigned int' values)' and ''__vector __pixel ' (vector of 8 'unsigned short' values)') is deprecated; in the future, the behavior implied by '-fno-lax-vector-conversions' will be the default}} + vp = vsi; // expected-warning {{implicit conversion between vector types (''__vector int' (vector of 4 'int' values)' and ''__vector __pixel ' (vector of 8 'unsigned short' values)') is deprecated; in the future, the behavior implied by '-fno-lax-vector-conversions' will be the default}} + vp = vui; // expected-warning {{implicit conversion between vector types (''__vector unsigned int' (vector of 4 'unsigned int' values)' and ''__vector __pixel ' (vector of 8 'unsigned short' values)') is deprecated; in the future, the behavior implied by '-fno-lax-vector-conversions' will be the default}} - vp = vbl; // expected-warning {{Implicit conversion between vector types (''__vector __bool unsigned long long' (vector of 2 'unsigned long long' values)' and ''__vector __pixel ' (vector of 8 'unsigned short' values)') is deprecated. In the future, the behavior implied by '-fno-lax-vector-conversions' will be the default.}} - vp = vsl; // expected-warning {{Implicit conversion between vector types (''__vector long long' (vector of 2 'long long' values)' and ''__vector __pixel ' (vector of 8 'unsigned short' values)') is deprecated. In the future, the behavior implied by '-fno-lax-vector-conversions' will be the default.}} - vp = vul; // expected-warning {{Implicit conversion between vector types (''__vector unsigned long long' (vector of 2 'unsigned long long' values)' and ''__vector __pixel ' (vector of 8 'unsigned short' values)') is deprecated. In the future, the behavior implied by '-fno-lax-vector-conversions' will be the default.}} + vp = vbl; // expected-warning {{implicit conversion between vector types (''__vector __bool unsigned long long' (vector of 2 'unsigned long long' values)' and ''__vector __pixel ' (vector of 8 'unsigned short' values)') is deprecated; in the future, the behavior implied by '-fno-lax-vector-conversions' will be the default}} + vp = vsl; // expected-warning {{implicit conversion between vector types (''__vector long long' (vector of 2 'long long' values)' and ''__vector __pixel ' (vector of 8 'unsigned short' values)') is deprecated; in the future, the behavior implied by '-fno-lax-vector-conversions' will be the default}} + vp = vul; // expected-warning {{implicit conversion between vector types (''__vector unsigned long long' (vector of 2 'unsigned long long' values)' and ''__vector __pixel ' (vector of 8 'unsigned short' values)') is deprecated; in the future, the behavior implied by '-fno-lax-vector-conversions' will be the default}} - vp = vbc; // expected-warning {{Implicit conversion between vector types (''__vector __bool unsigned char' (vector of 16 'unsigned char' values)' and ''__vector __pixel ' (vector of 8 'unsigned short' values)') is deprecated. In the future, the behavior implied by '-fno-lax-vector-conversions' will be the default.}} - vp = vsc; // expected-warning {{Implicit conversion between vector types (''__vector signed char' (vector of 16 'signed char' values)' and ''__vector __pixel ' (vector of 8 'unsigned short' values)') is deprecated. In the future, the behavior implied by '-fno-lax-vector-conversions' will be the default.}} - vp = vuc; // expected-warning {{Implicit conversion between vector types (''__vector unsigned char' (vector of 16 'unsigned char' values)' and ''__vector __pixel ' (vector of 8 'unsigned short' values)') is deprecated. In the future, the behavior implied by '-fno-lax-vector-conversions' will be the default.}} + vp = vbc; // expected-warning {{implicit conversion between vector types (''__vector __bool unsigned char' (vector of 16 'unsigned char' values)' and ''__vector __pixel ' (vector of 8 'unsigned short' values)') is deprecated; in the future, the behavior implied by '-fno-lax-vector-conversions' will be the default}} + vp = vsc; // expected-warning {{implicit conversion between vector types (''__vector signed char' (vector of 16 'signed char' values)' and ''__vector __pixel ' (vector of 8 'unsigned short' values)') is deprecated; in the future, the behavior implied by '-fno-lax-vector-conversions' will be the default}} + vp = vuc; // expected-warning {{implicit conversion between vector types (''__vector unsigned char' (vector of 16 'unsigned char' values)' and ''__vector __pixel ' (vector of 8 'unsigned short' values)') is deprecated; in the future, the behavior implied by '-fno-lax-vector-conversions' will be the default}} } -- GitLab From 337e633bb75640bb6e04eb874c7114dfac6fa754 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Storsj=C3=B6?= Date: Tue, 21 May 2024 22:34:38 +0300 Subject: [PATCH 032/452] [libcxx] [test] Detect mingw-w64 headers compatible with C++ module builds (#92893) This fixes running the tests/CI with a newer mingw toolchain that has been fixed to work with building libc++ as a module. --- libcxx/utils/libcxx/test/features.py | 35 +++++++++++++++++++++++++++- 1 file changed, 34 insertions(+), 1 deletion(-) diff --git a/libcxx/utils/libcxx/test/features.py b/libcxx/utils/libcxx/test/features.py index c81b56b1af54..093cd39ea64c 100644 --- a/libcxx/utils/libcxx/test/features.py +++ b/libcxx/utils/libcxx/test/features.py @@ -38,6 +38,39 @@ def _getAndroidDeviceApi(cfg): ) ) + +def _mingwSupportsModules(cfg): + # Only mingw headers are known to work with libc++ built as a module, + # at the moment. + if not "__MINGW32__" in compilerMacros(cfg): + return False + # For mingw headers, check for a version known to support being built + # as a module. + return sourceBuilds( + cfg, + """ + #include <_mingw_mac.h> + #if __MINGW64_VERSION_MAJOR < 12 + #error Headers known to be incompatible + #elif __MINGW64_VERSION_MAJOR == 12 + // The headers were fixed to work with libc++ modules during + // __MINGW64_VERSION_MAJOR == 12. The headers became compatible + // with libc++ built as a module in + // 1652e9241b5d8a5a779c6582b1c3c4f4a7cc66e5 (Apr 2024), but the + // following commit 8c13b28ace68f2c0094d45121d59a4b951b533ed + // removed the now unused __mingw_static_ovr define. Use this + // as indicator for whether we've got new enough headers. + #ifdef __mingw_static_ovr + #error Headers too old + #endif + #else + // __MINGW64_VERSION_MAJOR > 12 should be ok. + #endif + int main() { return 0; } + """, + ) + + # Lit features are evaluated in order. Some checks may require the compiler detection to have # run first in order to work properly. DEFAULT_FEATURES = [ @@ -281,7 +314,7 @@ DEFAULT_FEATURES = [ # Any declaration of a library function shall have external linkage. when=lambda cfg: "__ANDROID__" in compilerMacros(cfg) or "__FreeBSD__" in compilerMacros(cfg) - or "_WIN32" in compilerMacros(cfg) + or ("_WIN32" in compilerMacros(cfg) and not _mingwSupportsModules(cfg)) or platform.system().lower().startswith("aix") # Avoid building on platforms that don't support modules properly. or not hasCompileFlag(cfg, "-Wno-reserved-module-identifier"), -- GitLab From 57a507930b50c445140feb68bffe1c21af53319e Mon Sep 17 00:00:00 2001 From: Thurston Dang Date: Tue, 21 May 2024 12:41:36 -0700 Subject: [PATCH 033/452] [msan] Increase kNumStackOriginDescrs constant (#92838) This increases the constant size of kNumStackOriginDescrs to 4M (64GB of BSS across two arrays), which ought to be enough for anybody. This is the easier alternative suggested by eugenis@ in https://github.com/llvm/llvm-project/pull/92826. --- compiler-rt/lib/msan/msan.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/compiler-rt/lib/msan/msan.cpp b/compiler-rt/lib/msan/msan.cpp index a2fc27de1901..7a152910193e 100644 --- a/compiler-rt/lib/msan/msan.cpp +++ b/compiler-rt/lib/msan/msan.cpp @@ -100,7 +100,11 @@ int msan_report_count = 0; // Array of stack origins. // FIXME: make it resizable. -static const uptr kNumStackOriginDescrs = 1024 * 1024; +// Although BSS memory doesn't cost anything until used, it is limited to 2GB +// in some configurations (e.g., "relocation R_X86_64_PC32 out of range: +// ... is not in [-2147483648, 2147483647]; references section '.bss'"). +// We use kNumStackOriginDescrs * (sizeof(char*) + sizeof(uptr)) == 64MB. +static const uptr kNumStackOriginDescrs = 4 * 1024 * 1024; static const char *StackOriginDescr[kNumStackOriginDescrs]; static uptr StackOriginPC[kNumStackOriginDescrs]; static atomic_uint32_t NumStackOriginDescrs; -- GitLab From 0bc710f7c19910817ccff254c43496602635bbc9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Valentin=20Clement=20=28=E3=83=90=E3=83=AC=E3=83=B3?= =?UTF-8?q?=E3=82=BF=E3=82=A4=E3=83=B3=20=E3=82=AF=E3=83=AC=E3=83=A1?= =?UTF-8?q?=E3=83=B3=29?= Date: Tue, 21 May 2024 12:42:30 -0700 Subject: [PATCH 034/452] [flang][cuda] Accept constant as src for cuf.data_tranfer (#92951) Assignment of a constant (host) to a device variable is a special case that can be further lowered to `cudaMemset` or similar functions. This patch update the lowering to avoid the creation of a temporary when we assign a constant to a device variable. --- .../flang/Optimizer/Dialect/CUF/CUFOps.td | 2 +- flang/lib/Lower/Bridge.cpp | 17 ++++++++++++----- flang/lib/Optimizer/Dialect/CUF/CUFOps.cpp | 7 ++++++- flang/test/Lower/CUDA/cuda-data-transfer.cuf | 9 +++++---- 4 files changed, 24 insertions(+), 11 deletions(-) diff --git a/flang/include/flang/Optimizer/Dialect/CUF/CUFOps.td b/flang/include/flang/Optimizer/Dialect/CUF/CUFOps.td index f2992997c42c..37b8da018195 100644 --- a/flang/include/flang/Optimizer/Dialect/CUF/CUFOps.td +++ b/flang/include/flang/Optimizer/Dialect/CUF/CUFOps.td @@ -158,7 +158,7 @@ def cuf_DataTransferOp : cuf_Op<"data_transfer", []> { updated. }]; - let arguments = (ins Arg:$src, + let arguments = (ins Arg:$src, Arg:$dst, cuf_DataTransferKindAttr:$transfer_kind); diff --git a/flang/lib/Lower/Bridge.cpp b/flang/lib/Lower/Bridge.cpp index 3e0a6da7fc32..898b37504a6e 100644 --- a/flang/lib/Lower/Bridge.cpp +++ b/flang/lib/Lower/Bridge.cpp @@ -57,6 +57,7 @@ #include "flang/Semantics/symbol.h" #include "flang/Semantics/tools.h" #include "mlir/Dialect/ControlFlow/IR/ControlFlowOps.h" +#include "mlir/IR/Matchers.h" #include "mlir/IR/PatternMatch.h" #include "mlir/Parser/Parser.h" #include "mlir/Transforms/RegionUtils.h" @@ -3798,11 +3799,17 @@ private: auto transferKindAttr = cuf::DataTransferKindAttr::get( builder.getContext(), cuf::DataTransferKind::HostDevice); if (!rhs.isVariable()) { - auto associate = hlfir::genAssociateExpr( - loc, builder, rhs, rhs.getType(), ".cuf_host_tmp"); - builder.create(loc, associate.getBase(), lhsVal, - transferKindAttr); - builder.create(loc, associate); + // Special case if the rhs is a constant. + if (matchPattern(rhs.getDefiningOp(), mlir::m_Constant())) { + builder.create(loc, rhs, lhsVal, + transferKindAttr); + } else { + auto associate = hlfir::genAssociateExpr( + loc, builder, rhs, rhs.getType(), ".cuf_host_tmp"); + builder.create(loc, associate.getBase(), lhsVal, + transferKindAttr); + builder.create(loc, associate); + } } else { builder.create(loc, rhsVal, lhsVal, transferKindAttr); diff --git a/flang/lib/Optimizer/Dialect/CUF/CUFOps.cpp b/flang/lib/Optimizer/Dialect/CUF/CUFOps.cpp index 0446c1db86b1..2c0c4c2cfae3 100644 --- a/flang/lib/Optimizer/Dialect/CUF/CUFOps.cpp +++ b/flang/lib/Optimizer/Dialect/CUF/CUFOps.cpp @@ -99,7 +99,12 @@ mlir::LogicalResult cuf::DataTransferOp::verify() { if ((fir::isa_ref_type(srcTy) && fir::isa_ref_type(dstTy)) || (fir::isa_box_type(srcTy) && fir::isa_box_type(dstTy))) return mlir::success(); - return emitOpError("expect src and dst to be both references or descriptors"); + if (fir::isa_trivial(srcTy) && + matchPattern(getSrc().getDefiningOp(), mlir::m_Constant())) + return mlir::success(); + return emitOpError() + << "expect src and dst to be both references or descriptors or src to " + "be a constant"; } //===----------------------------------------------------------------------===// diff --git a/flang/test/Lower/CUDA/cuda-data-transfer.cuf b/flang/test/Lower/CUDA/cuda-data-transfer.cuf index e23792e6efc5..42fa4d09c95e 100644 --- a/flang/test/Lower/CUDA/cuda-data-transfer.cuf +++ b/flang/test/Lower/CUDA/cuda-data-transfer.cuf @@ -25,6 +25,8 @@ subroutine sub1() adev = ahost + bhost + adev = 10 + end ! CHECK-LABEL: func.func @_QPsub1() @@ -41,10 +43,7 @@ end ! CHECK: cuf.data_transfer %[[ASSOC]]#0 to %[[M]]#0 {transfer_kind = #cuf.cuda_transfer} : !fir.ref, !fir.ref ! CHECK: hlfir.end_associate %[[ASSOC]]#1, %[[ASSOC]]#2 : !fir.ref, i1 -! CHECK: %[[C1:.*]] = arith.constant 1 : i32 -! CHECK: %[[ASSOC:.*]]:3 = hlfir.associate %[[C1]] {uniq_name = ".cuf_host_tmp"} : (i32) -> (!fir.ref, !fir.ref, i1) -! CHECK: cuf.data_transfer %[[ASSOC]]#0 to %[[M]]#0 {transfer_kind = #cuf.cuda_transfer} : !fir.ref, !fir.ref -! CHECK: hlfir.end_associate %[[ASSOC]]#1, %[[ASSOC]]#2 : !fir.ref, i1 +! CHECK: cuf.data_transfer %c1{{.*}} to %[[M]]#0 {transfer_kind = #cuf.cuda_transfer} : i32, !fir.ref ! CHECK: cuf.data_transfer %[[AHOST]]#0 to %[[ADEV]]#0 {transfer_kind = #cuf.cuda_transfer} : !fir.ref>, !fir.ref> @@ -62,6 +61,8 @@ end ! CHECK: cuf.data_transfer %[[ASSOC]]#0 to %[[ADEV]]#0 {transfer_kind = #cuf.cuda_transfer} : !fir.ref>, !fir.ref> ! CHECK: hlfir.end_associate %[[ASSOC]]#1, %[[ASSOC]]#2 : !fir.ref>, i1 +! CHECK: cuf.data_transfer %c10{{.*}} to %[[ADEV]]#0 {transfer_kind = #cuf.cuda_transfer} : i32, !fir.ref> + subroutine sub2() integer, device :: m integer, device :: adev(10), bdev(10) -- GitLab From 687039bce91e90f87d68fb0c409baffaae16649e Mon Sep 17 00:00:00 2001 From: Craig Topper Date: Tue, 21 May 2024 13:07:56 -0700 Subject: [PATCH 035/452] [X86] Return true for opaque constants in hasAndNotCompare. (#92944) This is the X86 equivalent of #92926 --- llvm/lib/Target/X86/X86ISelLowering.cpp | 2 +- llvm/test/CodeGen/X86/pr90703.ll | 21 +++++++++++++++++++++ 2 files changed, 22 insertions(+), 1 deletion(-) create mode 100644 llvm/test/CodeGen/X86/pr90703.ll diff --git a/llvm/lib/Target/X86/X86ISelLowering.cpp b/llvm/lib/Target/X86/X86ISelLowering.cpp index 5d0846453685..24ee0c45b667 100644 --- a/llvm/lib/Target/X86/X86ISelLowering.cpp +++ b/llvm/lib/Target/X86/X86ISelLowering.cpp @@ -3292,7 +3292,7 @@ bool X86TargetLowering::hasAndNotCompare(SDValue Y) const { if (VT != MVT::i32 && VT != MVT::i64) return false; - return !isa(Y); + return !isa(Y) || cast(Y)->isOpaque(); } bool X86TargetLowering::hasAndNot(SDValue Y) const { diff --git a/llvm/test/CodeGen/X86/pr90703.ll b/llvm/test/CodeGen/X86/pr90703.ll new file mode 100644 index 000000000000..c02342ffeec1 --- /dev/null +++ b/llvm/test/CodeGen/X86/pr90703.ll @@ -0,0 +1,21 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 5 +; RUN: llc < %s -mtriple=x86_64-unknown-linux-gnu -mattr=+bmi | FileCheck %s + +define i64 @pr90730(i64 %x, i64 %y, ptr %p) { +; CHECK-LABEL: pr90730: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: movabsq $33181731808, %rax # imm = 0x7B9C90BE0 +; CHECK-NEXT: andnq %rax, %rdi, %rax +; CHECK-NEXT: movq $0, (%rdx) +; CHECK-NEXT: retq +entry: + %ext = and i64 %y, 1 + %xor1 = xor i64 %ext, 33181731817 + %and1 = and i64 %xor1, %x + store i64 %and1, ptr %p, align 4 + %v = load i64, ptr %p, align 4 + %and2 = and i64 %v, 33181731808 + %xor2 = xor i64 %and2, 33181731808 + store i64 0, ptr %p, align 4 + ret i64 %xor2 +} -- GitLab From 243611ed4ce69c3c6f94092f12fa5703dfcb2c9f Mon Sep 17 00:00:00 2001 From: Vlad Serebrennikov Date: Wed, 22 May 2024 00:14:45 +0400 Subject: [PATCH 036/452] Disable compiling and testing Flang on Clang changes (#92740) This patch aims to rectify the Windows CI situation by decoupling Clang changes from Flang test suite, which is causing Windows CI to "pause" for 20 minutes (details can be found [here](https://discourse.llvm.org/t/flang-tests-are-extremely-slow-on-windows/78591/11)). This even seems desirable in the long run, because it was highlighted that the only part of Clang that Flang depends on is Driver ([Discourse post](https://discourse.llvm.org/t/flang-tests-are-extremely-slow-on-windows/78591/14)). Importantly, this patch leaves the question of _entirely_ disabling Flang tests on Windows CI out of scope. --- .ci/generate-buildkite-pipeline-premerge | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.ci/generate-buildkite-pipeline-premerge b/.ci/generate-buildkite-pipeline-premerge index 78a9cb77ff7d..e1c66ac18e7a 100755 --- a/.ci/generate-buildkite-pipeline-premerge +++ b/.ci/generate-buildkite-pipeline-premerge @@ -68,7 +68,7 @@ function compute-projects-to-test() { done ;; clang) - for p in clang-tools-extra compiler-rt flang lldb cross-project-tests; do + for p in clang-tools-extra compiler-rt lldb cross-project-tests; do echo $p done ;; -- GitLab From 3eb7711e929f9b7ffaa0049a56ad70c4d99e4917 Mon Sep 17 00:00:00 2001 From: Igor Kudrin Date: Tue, 21 May 2024 13:19:21 -0700 Subject: [PATCH 037/452] [AArch64][PAC][NFC] Make checkAuthenticatedRegister() return void (#92507) The return value is not used. This change simplifies the upcoming fix --- llvm/lib/Target/AArch64/AArch64PointerAuth.cpp | 10 +++++----- llvm/lib/Target/AArch64/AArch64PointerAuth.h | 12 ++++-------- 2 files changed, 9 insertions(+), 13 deletions(-) diff --git a/llvm/lib/Target/AArch64/AArch64PointerAuth.cpp b/llvm/lib/Target/AArch64/AArch64PointerAuth.cpp index abde099be382..90bf089dbebf 100644 --- a/llvm/lib/Target/AArch64/AArch64PointerAuth.cpp +++ b/llvm/lib/Target/AArch64/AArch64PointerAuth.cpp @@ -231,7 +231,7 @@ MachineMemOperand *createCheckMemOperand(MachineFunction &MF, } // namespace -MachineBasicBlock &llvm::AArch64PAuth::checkAuthenticatedRegister( +void llvm::AArch64PAuth::checkAuthenticatedRegister( MachineBasicBlock::iterator MBBI, AuthCheckMethod Method, Register AuthenticatedReg, Register TmpReg, bool UseIKey, unsigned BrkImm) { @@ -246,13 +246,13 @@ MachineBasicBlock &llvm::AArch64PAuth::checkAuthenticatedRegister( default: break; case AuthCheckMethod::None: - return MBB; + return; case AuthCheckMethod::DummyLoad: BuildMI(MBB, MBBI, DL, TII->get(AArch64::LDRWui), getWRegFromXReg(TmpReg)) .addReg(AuthenticatedReg) .addImm(0) .addMemOperand(createCheckMemOperand(MF, Subtarget)); - return MBB; + return; } // Control flow has to be changed, so arrange new MBBs. @@ -287,7 +287,7 @@ MachineBasicBlock &llvm::AArch64PAuth::checkAuthenticatedRegister( .addReg(TmpReg) .addImm(62) .addMBB(BreakBlock); - return *SuccessBlock; + return; case AuthCheckMethod::XPACHint: assert(AuthenticatedReg == AArch64::LR && "XPACHint mode is only compatible with checking the LR register"); @@ -304,7 +304,7 @@ MachineBasicBlock &llvm::AArch64PAuth::checkAuthenticatedRegister( BuildMI(CheckBlock, DL, TII->get(AArch64::Bcc)) .addImm(AArch64CC::NE) .addMBB(BreakBlock); - return *SuccessBlock; + return; } llvm_unreachable("Unknown AuthCheckMethod enum"); } diff --git a/llvm/lib/Target/AArch64/AArch64PointerAuth.h b/llvm/lib/Target/AArch64/AArch64PointerAuth.h index e1ceaed58abe..4ffda7478224 100644 --- a/llvm/lib/Target/AArch64/AArch64PointerAuth.h +++ b/llvm/lib/Target/AArch64/AArch64PointerAuth.h @@ -98,14 +98,10 @@ enum class AuthCheckMethod { /// using an I-key or D-key and which register can be used as temporary. /// If an explicit BRK instruction is used to generate an exception, BrkImm /// specifies its immediate operand. -/// -/// \returns The machine basic block containing the code that is executed -/// after the check succeeds. -MachineBasicBlock &checkAuthenticatedRegister(MachineBasicBlock::iterator MBBI, - AuthCheckMethod Method, - Register AuthenticatedReg, - Register TmpReg, bool UseIKey, - unsigned BrkImm); +void checkAuthenticatedRegister(MachineBasicBlock::iterator MBBI, + AuthCheckMethod Method, + Register AuthenticatedReg, Register TmpReg, + bool UseIKey, unsigned BrkImm); /// Returns the number of bytes added by checkAuthenticatedRegister. unsigned getCheckerSizeInBytes(AuthCheckMethod Method); -- GitLab From 9f2313829fd210f9923375e93bc11fe9685c26d5 Mon Sep 17 00:00:00 2001 From: shaw young <58664393+shawbyoung@users.noreply.github.com> Date: Tue, 21 May 2024 13:26:57 -0700 Subject: [PATCH 038/452] [BOLT] Add NamedRegionTimer to inferStaleProfile (#92621) --- bolt/lib/Profile/StaleProfileMatching.cpp | 6 ++++++ bolt/lib/Rewrite/RewriteInstance.cpp | 7 +++---- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/bolt/lib/Profile/StaleProfileMatching.cpp b/bolt/lib/Profile/StaleProfileMatching.cpp index 016962ff34d8..712d9a121b5e 100644 --- a/bolt/lib/Profile/StaleProfileMatching.cpp +++ b/bolt/lib/Profile/StaleProfileMatching.cpp @@ -30,6 +30,7 @@ #include "llvm/ADT/Bitfields.h" #include "llvm/ADT/Hashing.h" #include "llvm/Support/CommandLine.h" +#include "llvm/Support/Timer.h" #include "llvm/Support/xxhash.h" #include "llvm/Transforms/Utils/SampleProfileInference.h" @@ -42,6 +43,7 @@ using namespace llvm; namespace opts { +extern cl::opt TimeRewrite; extern cl::OptionCategory BoltOptCategory; cl::opt @@ -705,6 +707,10 @@ void assignProfile(BinaryFunction &BF, bool YAMLProfileReader::inferStaleProfile( BinaryFunction &BF, const yaml::bolt::BinaryFunctionProfile &YamlBF) { + + NamedRegionTimer T("inferStaleProfile", "stale profile inference", "rewrite", + "Rewrite passes", opts::TimeRewrite); + if (!BF.hasCFG()) return false; diff --git a/bolt/lib/Rewrite/RewriteInstance.cpp b/bolt/lib/Rewrite/RewriteInstance.cpp index 6e1021a6df22..2559c9bd4800 100644 --- a/bolt/lib/Rewrite/RewriteInstance.cpp +++ b/bolt/lib/Rewrite/RewriteInstance.cpp @@ -235,10 +235,9 @@ UseGnuStack("use-gnu-stack", cl::ZeroOrMore, cl::cat(BoltCategory)); -static cl::opt - TimeRewrite("time-rewrite", - cl::desc("print time spent in rewriting passes"), cl::Hidden, - cl::cat(BoltCategory)); +cl::opt TimeRewrite("time-rewrite", + cl::desc("print time spent in rewriting passes"), + cl::Hidden, cl::cat(BoltCategory)); static cl::opt SequentialDisassembly("sequential-disassembly", -- GitLab From 32c9d5ef4fb171ad24dce91cdaa67683ccca2d78 Mon Sep 17 00:00:00 2001 From: Amir Ayupov Date: Tue, 21 May 2024 13:55:32 -0700 Subject: [PATCH 039/452] Revert "[BOLT] Add NamedRegionTimer to inferStaleProfile (#92621)" This reverts commit 9f2313829fd210f9923375e93bc11fe9685c26d5. Creates a dependency cycle: lib/Rewrite depends on lib/Profile. --- bolt/lib/Profile/StaleProfileMatching.cpp | 6 ------ bolt/lib/Rewrite/RewriteInstance.cpp | 7 ++++--- 2 files changed, 4 insertions(+), 9 deletions(-) diff --git a/bolt/lib/Profile/StaleProfileMatching.cpp b/bolt/lib/Profile/StaleProfileMatching.cpp index 712d9a121b5e..016962ff34d8 100644 --- a/bolt/lib/Profile/StaleProfileMatching.cpp +++ b/bolt/lib/Profile/StaleProfileMatching.cpp @@ -30,7 +30,6 @@ #include "llvm/ADT/Bitfields.h" #include "llvm/ADT/Hashing.h" #include "llvm/Support/CommandLine.h" -#include "llvm/Support/Timer.h" #include "llvm/Support/xxhash.h" #include "llvm/Transforms/Utils/SampleProfileInference.h" @@ -43,7 +42,6 @@ using namespace llvm; namespace opts { -extern cl::opt TimeRewrite; extern cl::OptionCategory BoltOptCategory; cl::opt @@ -707,10 +705,6 @@ void assignProfile(BinaryFunction &BF, bool YAMLProfileReader::inferStaleProfile( BinaryFunction &BF, const yaml::bolt::BinaryFunctionProfile &YamlBF) { - - NamedRegionTimer T("inferStaleProfile", "stale profile inference", "rewrite", - "Rewrite passes", opts::TimeRewrite); - if (!BF.hasCFG()) return false; diff --git a/bolt/lib/Rewrite/RewriteInstance.cpp b/bolt/lib/Rewrite/RewriteInstance.cpp index 2559c9bd4800..6e1021a6df22 100644 --- a/bolt/lib/Rewrite/RewriteInstance.cpp +++ b/bolt/lib/Rewrite/RewriteInstance.cpp @@ -235,9 +235,10 @@ UseGnuStack("use-gnu-stack", cl::ZeroOrMore, cl::cat(BoltCategory)); -cl::opt TimeRewrite("time-rewrite", - cl::desc("print time spent in rewriting passes"), - cl::Hidden, cl::cat(BoltCategory)); +static cl::opt + TimeRewrite("time-rewrite", + cl::desc("print time spent in rewriting passes"), cl::Hidden, + cl::cat(BoltCategory)); static cl::opt SequentialDisassembly("sequential-disassembly", -- GitLab From df626dd11c360c58eddae813ce6a0524d0a53696 Mon Sep 17 00:00:00 2001 From: Thurston Dang Date: Tue, 21 May 2024 21:45:37 +0000 Subject: [PATCH 040/452] Revert "[msan] Increase kNumStackOriginDescrs constant (#92838)" This reverts commit 57a507930b50c445140feb68bffe1c21af53319e. Reason: buildbot breakage (https://lab.llvm.org/buildbot/#/builders/57/builds/35160) --- compiler-rt/lib/msan/msan.cpp | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/compiler-rt/lib/msan/msan.cpp b/compiler-rt/lib/msan/msan.cpp index 7a152910193e..a2fc27de1901 100644 --- a/compiler-rt/lib/msan/msan.cpp +++ b/compiler-rt/lib/msan/msan.cpp @@ -100,11 +100,7 @@ int msan_report_count = 0; // Array of stack origins. // FIXME: make it resizable. -// Although BSS memory doesn't cost anything until used, it is limited to 2GB -// in some configurations (e.g., "relocation R_X86_64_PC32 out of range: -// ... is not in [-2147483648, 2147483647]; references section '.bss'"). -// We use kNumStackOriginDescrs * (sizeof(char*) + sizeof(uptr)) == 64MB. -static const uptr kNumStackOriginDescrs = 4 * 1024 * 1024; +static const uptr kNumStackOriginDescrs = 1024 * 1024; static const char *StackOriginDescr[kNumStackOriginDescrs]; static uptr StackOriginPC[kNumStackOriginDescrs]; static atomic_uint32_t NumStackOriginDescrs; -- GitLab From 3b3d622be993faa985ed9cbb9ab098c8d6b8f681 Mon Sep 17 00:00:00 2001 From: Andrew Browne Date: Tue, 21 May 2024 15:05:52 -0700 Subject: [PATCH 041/452] [DFSan] Fix recvmsg wrapper to support MSG_TRUNC flag. (#92599) The MSG_TRUNC flag makes recvmsg return the real length of the packet, even if it was too big to fit in the provided buffer. This is commonly used together with MSG_PEEK. Without this patch, dfsan's clear_msghdr_labels expects the return value of recvmsg (size recieved) to be less than or equal to the iov buffer length where recvmsg writes data, resulting in a crash. --- compiler-rt/lib/dfsan/dfsan_custom.cpp | 26 +++++++--- compiler-rt/test/dfsan/custom.cpp | 67 ++++++++++++++++++-------- 2 files changed, 65 insertions(+), 28 deletions(-) diff --git a/compiler-rt/lib/dfsan/dfsan_custom.cpp b/compiler-rt/lib/dfsan/dfsan_custom.cpp index 3af26e9f64c9..af3c1f4d1673 100644 --- a/compiler-rt/lib/dfsan/dfsan_custom.cpp +++ b/compiler-rt/lib/dfsan/dfsan_custom.cpp @@ -1901,17 +1901,27 @@ SANITIZER_INTERFACE_ATTRIBUTE int __dfso_nanosleep( return __dfsw_nanosleep(req, rem, req_label, rem_label, ret_label); } -static void clear_msghdr_labels(size_t bytes_written, struct msghdr *msg) { +static void clear_msghdr_labels(size_t bytes_written, struct msghdr *msg, + int flags) { dfsan_set_label(0, msg, sizeof(*msg)); dfsan_set_label(0, msg->msg_name, msg->msg_namelen); dfsan_set_label(0, msg->msg_control, msg->msg_controllen); - for (size_t i = 0; bytes_written > 0; ++i) { - assert(i < msg->msg_iovlen); + for (size_t i = 0; i < msg->msg_iovlen; ++i) { struct iovec *iov = &msg->msg_iov[i]; - size_t iov_written = - bytes_written < iov->iov_len ? bytes_written : iov->iov_len; + size_t iov_written = iov->iov_len; + + // When MSG_TRUNC is not set, we want to avoid setting 0 label on bytes that + // may not have changed, using bytes_written to bound the 0 label write. + // When MSG_TRUNC flag is set, bytes_written may be larger than the buffer, + // and should not be used as a bound. + if (!(MSG_TRUNC & flags)) { + if (bytes_written < iov->iov_len) { + iov_written = bytes_written; + } + bytes_written -= iov_written; + } + dfsan_set_label(0, iov->iov_base, iov_written); - bytes_written -= iov_written; } } @@ -1923,7 +1933,7 @@ SANITIZER_INTERFACE_ATTRIBUTE int __dfsw_recvmmsg( int ret = recvmmsg(sockfd, msgvec, vlen, flags, timeout); for (int i = 0; i < ret; ++i) { dfsan_set_label(0, &msgvec[i].msg_len, sizeof(msgvec[i].msg_len)); - clear_msghdr_labels(msgvec[i].msg_len, &msgvec[i].msg_hdr); + clear_msghdr_labels(msgvec[i].msg_len, &msgvec[i].msg_hdr, flags); } *ret_label = 0; return ret; @@ -1947,7 +1957,7 @@ SANITIZER_INTERFACE_ATTRIBUTE ssize_t __dfsw_recvmsg( dfsan_label msg_label, dfsan_label flags_label, dfsan_label *ret_label) { ssize_t ret = recvmsg(sockfd, msg, flags); if (ret >= 0) - clear_msghdr_labels(ret, msg); + clear_msghdr_labels(ret, msg, flags); *ret_label = 0; return ret; } diff --git a/compiler-rt/test/dfsan/custom.cpp b/compiler-rt/test/dfsan/custom.cpp index f544e481b726..cede0d64dbcf 100644 --- a/compiler-rt/test/dfsan/custom.cpp +++ b/compiler-rt/test/dfsan/custom.cpp @@ -768,26 +768,53 @@ void test_recvmsg() { ssize_t sent = sendmsg(sockfds[0], &smsg, 0); assert(sent > 0); - char rbuf[128]; - struct iovec riovs[2] = {{&rbuf[0], 4}, {&rbuf[4], 4}}; - struct msghdr rmsg = {}; - rmsg.msg_iov = riovs; - rmsg.msg_iovlen = 2; - - dfsan_set_label(i_label, rbuf, sizeof(rbuf)); - dfsan_set_label(i_label, &rmsg, sizeof(rmsg)); - - DEFINE_AND_SAVE_ORIGINS(rmsg) - - ssize_t received = recvmsg(sockfds[1], &rmsg, 0); - assert(received == sent); - assert(memcmp(sbuf, rbuf, 8) == 0); - ASSERT_ZERO_LABEL(received); - ASSERT_READ_ZERO_LABEL(&rmsg, sizeof(rmsg)); - ASSERT_READ_ZERO_LABEL(&rbuf[0], 8); - ASSERT_READ_LABEL(&rbuf[8], 1, i_label); - - ASSERT_SAVED_ORIGINS(rmsg) + { + char rpbuf[2]; + struct iovec peek_iov; + peek_iov.iov_base = rpbuf; + peek_iov.iov_len = 2; + + struct msghdr peek_header = {}; + peek_header.msg_iov = &peek_iov; + peek_header.msg_iovlen = 1; + + dfsan_set_label(i_label, rpbuf, sizeof(rpbuf)); + dfsan_set_label(i_label, &peek_header, sizeof(peek_header)); + + DEFINE_AND_SAVE_ORIGINS(peek_header) + + ssize_t received = recvmsg(sockfds[1], &peek_header, MSG_PEEK | MSG_TRUNC); + assert(received == sent); + assert(memcmp(sbuf, rpbuf, 2) == 0); + ASSERT_ZERO_LABEL(received); + ASSERT_READ_ZERO_LABEL(&peek_header, sizeof(peek_header)); + ASSERT_READ_ZERO_LABEL(&rpbuf[0], 0); + + ASSERT_SAVED_ORIGINS(peek_header) + } + + { + char rbuf[128]; + struct iovec riovs[2] = {{&rbuf[0], 4}, {&rbuf[4], 4}}; + struct msghdr rmsg = {}; + rmsg.msg_iov = riovs; + rmsg.msg_iovlen = 2; + + dfsan_set_label(i_label, rbuf, sizeof(rbuf)); + dfsan_set_label(i_label, &rmsg, sizeof(rmsg)); + + DEFINE_AND_SAVE_ORIGINS(rmsg) + + ssize_t received = recvmsg(sockfds[1], &rmsg, 0); + assert(received == sent); + assert(memcmp(sbuf, rbuf, 8) == 0); + ASSERT_ZERO_LABEL(received); + ASSERT_READ_ZERO_LABEL(&rmsg, sizeof(rmsg)); + ASSERT_READ_ZERO_LABEL(&rbuf[0], 8); + ASSERT_READ_LABEL(&rbuf[8], 1, i_label); + + ASSERT_SAVED_ORIGINS(rmsg) + } close(sockfds[0]); close(sockfds[1]); -- GitLab From 3a913d30bef061be9786740e14bacd3fa6d76adc Mon Sep 17 00:00:00 2001 From: Vlad Serebrennikov Date: Wed, 22 May 2024 02:07:28 +0400 Subject: [PATCH 042/452] [clang][NFC] Refactor `Sema::TagUseKind` (#92689) This patch makes `TagUseKind` a scoped enumeration, and moves it outside of `Sema` class, making it eligible for forward declaring. --- clang/include/clang/Parse/Parser.h | 2 +- clang/include/clang/Sema/Sema.h | 14 ++-- clang/lib/Parse/ParseDecl.cpp | 33 +++++---- clang/lib/Parse/ParseDeclCXX.cpp | 50 +++++++------- clang/lib/Sema/SemaDecl.cpp | 91 ++++++++++++------------ clang/lib/Sema/SemaDeclCXX.cpp | 13 ++-- clang/lib/Sema/SemaTemplate.cpp | 107 +++++++++++++++-------------- 7 files changed, 160 insertions(+), 150 deletions(-) diff --git a/clang/include/clang/Parse/Parser.h b/clang/include/clang/Parse/Parser.h index 3c4ab649e3b4..cc6d93384f80 100644 --- a/clang/include/clang/Parse/Parser.h +++ b/clang/include/clang/Parse/Parser.h @@ -2814,7 +2814,7 @@ private: SourceLocation CorrectLocation); void stripTypeAttributesOffDeclSpec(ParsedAttributes &Attrs, DeclSpec &DS, - Sema::TagUseKind TUK); + TagUseKind TUK); // FixItLoc = possible correct location for the attributes void ProhibitAttributes(ParsedAttributes &Attrs, diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index 01ddba5eaf01..8eaf569cb64d 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -447,6 +447,13 @@ enum class CheckedConversionKind { ForBuiltinOverloadedOp }; +enum class TagUseKind { + Reference, // Reference to a tag: 'struct foo *X;' + Declaration, // Fwd decl of a tag: 'struct foo;' + Definition, // Definition of a tag: 'struct foo { int X; } Y;' + Friend // Friend declaration: 'friend struct foo;' +}; + /// Sema - This implements semantic analysis and AST building for C. /// \nosubgrouping class Sema final : public SemaBase { @@ -3168,13 +3175,6 @@ public: bool isDefinition, SourceLocation NewTagLoc, const IdentifierInfo *Name); - enum TagUseKind { - TUK_Reference, // Reference to a tag: 'struct foo *X;' - TUK_Declaration, // Fwd decl of a tag: 'struct foo;' - TUK_Definition, // Definition of a tag: 'struct foo { int X; } Y;' - TUK_Friend // Friend declaration: 'friend struct foo;' - }; - enum OffsetOfKind { // Not parsing a type within __builtin_offsetof. OOK_Outside, diff --git a/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp index 445d3fd66e38..651ef7b78c94 100644 --- a/clang/lib/Parse/ParseDecl.cpp +++ b/clang/lib/Parse/ParseDecl.cpp @@ -1923,9 +1923,8 @@ void Parser::DiagnoseCXX11AttributeExtension(ParsedAttributes &Attrs) { // variable. // This function moves attributes that should apply to the type off DS to Attrs. void Parser::stripTypeAttributesOffDeclSpec(ParsedAttributes &Attrs, - DeclSpec &DS, - Sema::TagUseKind TUK) { - if (TUK == Sema::TUK_Reference) + DeclSpec &DS, TagUseKind TUK) { + if (TUK == TagUseKind::Reference) return; llvm::SmallVector ToBeMoved; @@ -5287,9 +5286,9 @@ void Parser::ParseEnumSpecifier(SourceLocation StartLoc, DeclSpec &DS, // enum foo {..}; void bar() { enum foo; } <- new foo in bar. // enum foo {..}; void bar() { enum foo x; } <- use of old foo. // - Sema::TagUseKind TUK; + TagUseKind TUK; if (AllowEnumSpecifier == AllowDefiningTypeSpec::No) - TUK = Sema::TUK_Reference; + TUK = TagUseKind::Reference; else if (Tok.is(tok::l_brace)) { if (DS.isFriendSpecified()) { Diag(Tok.getLocation(), diag::err_friend_decl_defines_type) @@ -5301,9 +5300,9 @@ void Parser::ParseEnumSpecifier(SourceLocation StartLoc, DeclSpec &DS, ScopedEnumKWLoc = SourceLocation(); IsScopedUsingClassTag = false; BaseType = TypeResult(); - TUK = Sema::TUK_Friend; + TUK = TagUseKind::Friend; } else { - TUK = Sema::TUK_Definition; + TUK = TagUseKind::Definition; } } else if (!isTypeSpecifier(DSC) && (Tok.is(tok::semi) || @@ -5312,7 +5311,7 @@ void Parser::ParseEnumSpecifier(SourceLocation StartLoc, DeclSpec &DS, // An opaque-enum-declaration is required to be standalone (no preceding or // following tokens in the declaration). Sema enforces this separately by // diagnosing anything else in the DeclSpec. - TUK = DS.isFriendSpecified() ? Sema::TUK_Friend : Sema::TUK_Declaration; + TUK = DS.isFriendSpecified() ? TagUseKind::Friend : TagUseKind::Declaration; if (Tok.isNot(tok::semi)) { // A semicolon was missing after this declaration. Diagnose and recover. ExpectAndConsume(tok::semi, diag::err_expected_after, "enum"); @@ -5320,21 +5319,21 @@ void Parser::ParseEnumSpecifier(SourceLocation StartLoc, DeclSpec &DS, Tok.setKind(tok::semi); } } else { - TUK = Sema::TUK_Reference; + TUK = TagUseKind::Reference; } bool IsElaboratedTypeSpecifier = - TUK == Sema::TUK_Reference || TUK == Sema::TUK_Friend; + TUK == TagUseKind::Reference || TUK == TagUseKind::Friend; // If this is an elaborated type specifier nested in a larger declaration, // and we delayed diagnostics before, just merge them into the current pool. - if (TUK == Sema::TUK_Reference && shouldDelayDiagsInTag) { + if (TUK == TagUseKind::Reference && shouldDelayDiagsInTag) { diagsFromTag.redelay(); } MultiTemplateParamsArg TParams; if (TemplateInfo.Kind != ParsedTemplateInfo::NonTemplate && - TUK != Sema::TUK_Reference) { + TUK != TagUseKind::Reference) { if (!getLangOpts().CPlusPlus11 || !SS.isSet()) { // Skip the rest of this declarator, up until the comma or semicolon. Diag(Tok, diag::err_enum_template); @@ -5355,7 +5354,7 @@ void Parser::ParseEnumSpecifier(SourceLocation StartLoc, DeclSpec &DS, SS.setTemplateParamLists(TParams); } - if (!Name && TUK != Sema::TUK_Definition) { + if (!Name && TUK != TagUseKind::Definition) { Diag(Tok, diag::err_enumerator_unnamed_no_def); DS.SetTypeSpecError(); @@ -5388,7 +5387,7 @@ void Parser::ParseEnumSpecifier(SourceLocation StartLoc, DeclSpec &DS, stripTypeAttributesOffDeclSpec(attrs, DS, TUK); SkipBodyInfo SkipBody; - if (!Name && TUK == Sema::TUK_Definition && Tok.is(tok::l_brace) && + if (!Name && TUK == TagUseKind::Definition && Tok.is(tok::l_brace) && NextToken().is(tok::identifier)) SkipBody = Actions.shouldSkipAnonEnumBody(getCurScope(), NextToken().getIdentifierInfo(), @@ -5409,7 +5408,7 @@ void Parser::ParseEnumSpecifier(SourceLocation StartLoc, DeclSpec &DS, OffsetOfState, &SkipBody).get(); if (SkipBody.ShouldSkip) { - assert(TUK == Sema::TUK_Definition && "can only skip a definition"); + assert(TUK == TagUseKind::Definition && "can only skip a definition"); BalancedDelimiterTracker T(*this, tok::l_brace); T.consumeOpen(); @@ -5451,7 +5450,7 @@ void Parser::ParseEnumSpecifier(SourceLocation StartLoc, DeclSpec &DS, if (!TagDecl) { // The action failed to produce an enumeration tag. If this is a // definition, consume the entire definition. - if (Tok.is(tok::l_brace) && TUK != Sema::TUK_Reference) { + if (Tok.is(tok::l_brace) && TUK != TagUseKind::Reference) { ConsumeBrace(); SkipUntil(tok::r_brace, StopAtSemi); } @@ -5460,7 +5459,7 @@ void Parser::ParseEnumSpecifier(SourceLocation StartLoc, DeclSpec &DS, return; } - if (Tok.is(tok::l_brace) && TUK == Sema::TUK_Definition) { + if (Tok.is(tok::l_brace) && TUK == TagUseKind::Definition) { Decl *D = SkipBody.CheckSameAsPrevious ? SkipBody.New : TagDecl; ParseEnumBody(StartLoc, D); if (SkipBody.CheckSameAsPrevious && diff --git a/clang/lib/Parse/ParseDeclCXX.cpp b/clang/lib/Parse/ParseDeclCXX.cpp index 5eaec2b621e6..805651e4ab06 100644 --- a/clang/lib/Parse/ParseDeclCXX.cpp +++ b/clang/lib/Parse/ParseDeclCXX.cpp @@ -1961,11 +1961,11 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind, MaybeParseCXX11Attributes(Attributes); const PrintingPolicy &Policy = Actions.getASTContext().getPrintingPolicy(); - Sema::TagUseKind TUK; + TagUseKind TUK; if (isDefiningTypeSpecifierContext(DSC, getLangOpts().CPlusPlus) == AllowDefiningTypeSpec::No || (getLangOpts().OpenMP && OpenMPDirectiveParsing)) - TUK = Sema::TUK_Reference; + TUK = TagUseKind::Reference; else if (Tok.is(tok::l_brace) || (DSC != DeclSpecContext::DSC_association && getLangOpts().CPlusPlus && Tok.is(tok::colon)) || @@ -1980,10 +1980,10 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind, // Skip everything up to the semicolon, so that this looks like a proper // friend class (or template thereof) declaration. SkipUntil(tok::semi, StopBeforeMatch); - TUK = Sema::TUK_Friend; + TUK = TagUseKind::Friend; } else { // Okay, this is a class definition. - TUK = Sema::TUK_Definition; + TUK = TagUseKind::Definition; } } else if (isClassCompatibleKeyword() && (NextToken().is(tok::l_square) || @@ -2024,15 +2024,15 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind, } if (Tok.isOneOf(tok::l_brace, tok::colon)) - TUK = Sema::TUK_Definition; + TUK = TagUseKind::Definition; else - TUK = Sema::TUK_Reference; + TUK = TagUseKind::Reference; PA.Revert(); } else if (!isTypeSpecifier(DSC) && (Tok.is(tok::semi) || (Tok.isAtStartOfLine() && !isValidAfterTypeSpecifier(false)))) { - TUK = DS.isFriendSpecified() ? Sema::TUK_Friend : Sema::TUK_Declaration; + TUK = DS.isFriendSpecified() ? TagUseKind::Friend : TagUseKind::Declaration; if (Tok.isNot(tok::semi)) { const PrintingPolicy &PPol = Actions.getASTContext().getPrintingPolicy(); // A semicolon was missing after this declaration. Diagnose and recover. @@ -2042,11 +2042,11 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind, Tok.setKind(tok::semi); } } else - TUK = Sema::TUK_Reference; + TUK = TagUseKind::Reference; // Forbid misplaced attributes. In cases of a reference, we pass attributes // to caller to handle. - if (TUK != Sema::TUK_Reference) { + if (TUK != TagUseKind::Reference) { // If this is not a reference, then the only possible // valid place for C++11 attributes to appear here // is between class-key and class-name. If there are @@ -2072,7 +2072,7 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind, if (!Name && !TemplateId && (DS.getTypeSpecType() == DeclSpec::TST_error || - TUK != Sema::TUK_Definition)) { + TUK != TagUseKind::Definition)) { if (DS.getTypeSpecType() != DeclSpec::TST_error) { // We have a declaration or reference to an anonymous class. Diag(StartLoc, diag::err_anon_type_definition) @@ -2082,7 +2082,7 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind, // If we are parsing a definition and stop at a base-clause, continue on // until the semicolon. Continuing from the comma will just trick us into // thinking we are seeing a variable declaration. - if (TUK == Sema::TUK_Definition && Tok.is(tok::colon)) + if (TUK == TagUseKind::Definition && Tok.is(tok::colon)) SkipUntil(tok::semi, StopBeforeMatch); else SkipUntil(tok::comma, StopAtSemi); @@ -2103,7 +2103,7 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind, if (TemplateId->isInvalid()) { // Can't build the declaration. } else if (TemplateInfo.Kind == ParsedTemplateInfo::ExplicitInstantiation && - TUK == Sema::TUK_Declaration) { + TUK == TagUseKind::Declaration) { // This is an explicit instantiation of a class template. ProhibitCXX11Attributes(attrs, diag::err_attributes_not_allowed, diag::err_keyword_not_allowed, @@ -2119,8 +2119,8 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind, // they have template headers, in which case they're ill-formed // (FIXME: "template friend class A::B;"). // We diagnose this error in ActOnClassTemplateSpecialization. - } else if (TUK == Sema::TUK_Reference || - (TUK == Sema::TUK_Friend && + } else if (TUK == TagUseKind::Reference || + (TUK == TagUseKind::Friend && TemplateInfo.Kind == ParsedTemplateInfo::NonTemplate)) { ProhibitCXX11Attributes(attrs, diag::err_attributes_not_allowed, diag::err_keyword_not_allowed, @@ -2145,10 +2145,10 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind, // It this is friend declaration however, since it cannot have a // template header, it is most likely that the user meant to // remove the 'template' keyword. - assert((TUK == Sema::TUK_Definition || TUK == Sema::TUK_Friend) && + assert((TUK == TagUseKind::Definition || TUK == TagUseKind::Friend) && "Expected a definition here"); - if (TUK == Sema::TUK_Friend) { + if (TUK == TagUseKind::Friend) { Diag(DS.getFriendSpecLoc(), diag::err_friend_explicit_instantiation); TemplateParams = nullptr; } else { @@ -2179,7 +2179,7 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind, &SkipBody); } } else if (TemplateInfo.Kind == ParsedTemplateInfo::ExplicitInstantiation && - TUK == Sema::TUK_Declaration) { + TUK == TagUseKind::Declaration) { // Explicit instantiation of a member of a class template // specialization, e.g., // @@ -2190,7 +2190,7 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind, TagOrTempResult = Actions.ActOnExplicitInstantiation( getCurScope(), TemplateInfo.ExternLoc, TemplateInfo.TemplateLoc, TagType, StartLoc, SS, Name, NameLoc, attrs); - } else if (TUK == Sema::TUK_Friend && + } else if (TUK == TagUseKind::Friend && TemplateInfo.Kind != ParsedTemplateInfo::NonTemplate) { ProhibitCXX11Attributes(attrs, diag::err_attributes_not_allowed, diag::err_keyword_not_allowed, @@ -2202,12 +2202,12 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind, MultiTemplateParamsArg(TemplateParams ? &(*TemplateParams)[0] : nullptr, TemplateParams ? TemplateParams->size() : 0)); } else { - if (TUK != Sema::TUK_Declaration && TUK != Sema::TUK_Definition) + if (TUK != TagUseKind::Declaration && TUK != TagUseKind::Definition) ProhibitCXX11Attributes(attrs, diag::err_attributes_not_allowed, diag::err_keyword_not_allowed, /* DiagnoseEmptyAttrs=*/true); - if (TUK == Sema::TUK_Definition && + if (TUK == TagUseKind::Definition && TemplateInfo.Kind == ParsedTemplateInfo::ExplicitInstantiation) { // If the declarator-id is not a template-id, issue a diagnostic and // recover by ignoring the 'template' keyword. @@ -2222,7 +2222,7 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind, // reference. For example, we don't need the template parameters here: // template class A *makeA(T t); MultiTemplateParamsArg TParams; - if (TUK != Sema::TUK_Reference && TemplateParams) + if (TUK != TagUseKind::Reference && TemplateParams) TParams = MultiTemplateParamsArg(&(*TemplateParams)[0], TemplateParams->size()); @@ -2241,7 +2241,7 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind, // If ActOnTag said the type was dependent, try again with the // less common call. if (IsDependent) { - assert(TUK == Sema::TUK_Reference || TUK == Sema::TUK_Friend); + assert(TUK == TagUseKind::Reference || TUK == TagUseKind::Friend); TypeResult = Actions.ActOnDependentTag(getCurScope(), TagType, TUK, SS, Name, StartLoc, NameLoc); } @@ -2252,13 +2252,13 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind, // just merge them into the current pool. if (shouldDelayDiagsInTag) { diagsFromTag.done(); - if (TUK == Sema::TUK_Reference && + if (TUK == TagUseKind::Reference && TemplateInfo.Kind == ParsedTemplateInfo::Template) diagsFromTag.redelay(); } // If there is a body, parse it and inform the actions module. - if (TUK == Sema::TUK_Definition) { + if (TUK == TagUseKind::Definition) { assert(Tok.is(tok::l_brace) || (getLangOpts().CPlusPlus && Tok.is(tok::colon)) || isClassCompatibleKeyword()); @@ -2316,7 +2316,7 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind, // // After a type-specifier, we don't expect a semicolon. This only happens in // C, since definitions are not permitted in this context in C++. - if (TUK == Sema::TUK_Definition && + if (TUK == TagUseKind::Definition && (getLangOpts().CPlusPlus || !isTypeSpecifier(DSC)) && (TemplateInfo.Kind || !isValidAfterTypeSpecifier(false))) { if (Tok.isNot(tok::semi)) { diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index 7f6921ea22be..6e60ec761b25 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -4989,7 +4989,7 @@ void Sema::setTagNameForLinkagePurposes(TagDecl *TagFromDeclSpec, if (TagFromDeclSpec->hasNameForLinkage()) return; - // A well-formed anonymous tag must always be a TUK_Definition. + // A well-formed anonymous tag must always be a TagUseKind::Definition. assert(TagFromDeclSpec->isThisDeclarationADefinition()); // The type must match the tag exactly; no qualifiers allowed. @@ -17242,9 +17242,9 @@ Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK, SourceLocation KWLoc, OffsetOfKind OOK, SkipBodyInfo *SkipBody) { // If this is not a definition, it must have a name. IdentifierInfo *OrigName = Name; - assert((Name != nullptr || TUK == TUK_Definition) && + assert((Name != nullptr || TUK == TagUseKind::Definition) && "Nameless record must be a definition!"); - assert(TemplateParameterLists.size() == 0 || TUK != TUK_Reference); + assert(TemplateParameterLists.size() == 0 || TUK != TagUseKind::Reference); OwnedDecl = false; TagTypeKind Kind = TypeWithKeyword::getTagTypeKindForTypeSpec(TagSpec); @@ -17258,11 +17258,11 @@ Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK, SourceLocation KWLoc, // or a scope specifier, which also conveniently avoids this work // for non-C++ cases. if (TemplateParameterLists.size() > 0 || - (SS.isNotEmpty() && TUK != TUK_Reference)) { + (SS.isNotEmpty() && TUK != TagUseKind::Reference)) { TemplateParameterList *TemplateParams = MatchTemplateParametersToScopeSpecifier( KWLoc, NameLoc, SS, nullptr, TemplateParameterLists, - TUK == TUK_Friend, isMemberSpecialization, Invalid); + TUK == TagUseKind::Friend, isMemberSpecialization, Invalid); // C++23 [dcl.type.elab] p2: // If an elaborated-type-specifier is the sole constituent of a @@ -17277,7 +17277,8 @@ Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK, SourceLocation KWLoc, // FIXME: Class template partial specializations can be forward declared // per CWG2213, but the resolution failed to allow qualified forward // declarations. This is almost certainly unintentional, so we allow them. - if (TUK == TUK_Declaration && SS.isNotEmpty() && !isMemberSpecialization) + if (TUK == TagUseKind::Declaration && SS.isNotEmpty() && + !isMemberSpecialization) Diag(SS.getBeginLoc(), diag::err_standalone_class_nested_name_specifier) << TypeWithKeyword::getTagTypeKindName(Kind) << SS.getRange(); @@ -17314,7 +17315,7 @@ Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK, SourceLocation KWLoc, return true; } - if (TUK == TUK_Friend && Kind == TagTypeKind::Enum) { + if (TUK == TagUseKind::Friend && Kind == TagTypeKind::Enum) { // C++23 [dcl.type.elab]p4: // If an elaborated-type-specifier appears with the friend specifier as // an entire member-declaration, the member-declaration shall have one @@ -17365,7 +17366,7 @@ Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK, SourceLocation KWLoc, // of 'int'. However, if this is an unfixed forward declaration, don't set // the underlying type unless the user enables -fms-compatibility. This // makes unfixed forward declared enums incomplete and is more conforming. - if (TUK == TUK_Definition || getLangOpts().MSVCCompat) + if (TUK == TagUseKind::Definition || getLangOpts().MSVCCompat) EnumUnderlying = Context.IntTy.getTypePtr(); } } @@ -17376,7 +17377,7 @@ Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK, SourceLocation KWLoc, bool isStdAlignValT = false; RedeclarationKind Redecl = forRedeclarationInCurContext(); - if (TUK == TUK_Friend || TUK == TUK_Reference) + if (TUK == TagUseKind::Friend || TUK == TagUseKind::Reference) Redecl = RedeclarationKind::NotForRedeclaration; /// Create a new tag decl in C/ObjC. Since the ODR-like semantics for ObjC/C @@ -17394,7 +17395,7 @@ Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK, SourceLocation KWLoc, New = EnumDecl::Create(Context, SearchDC, KWLoc, Loc, Name, nullptr, ScopedEnum, ScopedEnumUsesClassTag, IsFixed); // If this is an undefined enum, bail. - if (TUK != TUK_Definition && !Invalid) + if (TUK != TagUseKind::Definition && !Invalid) return nullptr; if (EnumUnderlying) { EnumDecl *ED = cast(New); @@ -17422,7 +17423,8 @@ Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK, SourceLocation KWLoc, // many points during the parsing of a struct declaration (because // the #pragma tokens are effectively skipped over during the // parsing of the struct). - if (TUK == TUK_Definition && (!SkipBody || !SkipBody->ShouldSkip)) { + if (TUK == TagUseKind::Definition && + (!SkipBody || !SkipBody->ShouldSkip)) { AddAlignmentAttributesForRecord(RD); AddMsStructLayoutForRecord(RD); } @@ -17443,7 +17445,7 @@ Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK, SourceLocation KWLoc, // If this is a friend or a reference to a class in a dependent // context, don't try to make a decl for it. - if (TUK == TUK_Friend || TUK == TUK_Reference) { + if (TUK == TagUseKind::Friend || TUK == TagUseKind::Reference) { DC = computeDeclContext(SS, false); if (!DC) { IsDependent = true; @@ -17476,7 +17478,7 @@ Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK, SourceLocation KWLoc, // this as a dependent elaborated-type-specifier. // But this only makes any sense for reference-like lookups. if (Previous.wasNotFoundInCurrentInstantiation() && - (TUK == TUK_Reference || TUK == TUK_Friend)) { + (TUK == TagUseKind::Reference || TUK == TagUseKind::Friend)) { IsDependent = true; return true; } @@ -17493,7 +17495,7 @@ Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK, SourceLocation KWLoc, // If T is the name of a class, then each of the following shall have a // name different from T: // -- every member of class T that is itself a type - if (TUK != TUK_Reference && TUK != TUK_Friend && + if (TUK != TagUseKind::Reference && TUK != TagUseKind::Friend && DiagnoseClassNameShadow(SearchDC, DeclarationNameInfo(Name, NameLoc))) return true; @@ -17507,7 +17509,7 @@ Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK, SourceLocation KWLoc, // When declaring or defining a tag, ignore ambiguities introduced // by types using'ed into this scope. if (Previous.isAmbiguous() && - (TUK == TUK_Definition || TUK == TUK_Declaration)) { + (TUK == TagUseKind::Definition || TUK == TagUseKind::Declaration)) { LookupResult::Filter F = Previous.makeFilter(); while (F.hasNext()) { NamedDecl *ND = F.next(); @@ -17531,7 +17533,7 @@ Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK, SourceLocation KWLoc, // // Does it matter that this should be by scope instead of by // semantic context? - if (!Previous.empty() && TUK == TUK_Friend) { + if (!Previous.empty() && TUK == TagUseKind::Friend) { DeclContext *EnclosingNS = SearchDC->getEnclosingNamespaceContext(); LookupResult::Filter F = Previous.makeFilter(); bool FriendSawTagOutsideEnclosingNamespace = false; @@ -17561,7 +17563,7 @@ Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK, SourceLocation KWLoc, if (Previous.isAmbiguous()) return true; - if (!getLangOpts().CPlusPlus && TUK != TUK_Reference) { + if (!getLangOpts().CPlusPlus && TUK != TagUseKind::Reference) { // FIXME: This makes sure that we ignore the contexts associated // with C structs, unions, and enums when looking for a matching // tag declaration or definition. See the similar lookup tweak @@ -17613,11 +17615,12 @@ Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK, SourceLocation KWLoc, // also need to do a redeclaration lookup there, just in case // there's a shadow friend decl. if (Name && Previous.empty() && - (TUK == TUK_Reference || TUK == TUK_Friend || IsTemplateParamOrArg)) { + (TUK == TagUseKind::Reference || TUK == TagUseKind::Friend || + IsTemplateParamOrArg)) { if (Invalid) goto CreateNewDecl; assert(SS.isEmpty()); - if (TUK == TUK_Reference || IsTemplateParamOrArg) { + if (TUK == TagUseKind::Reference || IsTemplateParamOrArg) { // C++ [basic.scope.pdecl]p5: // -- for an elaborated-type-specifier of the form // @@ -17651,7 +17654,7 @@ Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK, SourceLocation KWLoc, // Find the scope where we'll be declaring the tag. S = getTagInjectionScope(S, getLangOpts()); } else { - assert(TUK == TUK_Friend); + assert(TUK == TagUseKind::Friend); CXXRecordDecl *RD = dyn_cast(SearchDC); // C++ [namespace.memdef]p3: @@ -17716,7 +17719,8 @@ Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK, SourceLocation KWLoc, // redefinition if either context is within the other. if (auto *Shadow = dyn_cast(DirectPrevDecl)) { auto *OldTag = dyn_cast(PrevDecl); - if (SS.isEmpty() && TUK != TUK_Reference && TUK != TUK_Friend && + if (SS.isEmpty() && TUK != TagUseKind::Reference && + TUK != TagUseKind::Friend && isDeclInScope(Shadow, SearchDC, S, isMemberSpecialization) && !(OldTag && isAcceptableTagRedeclContext( *this, OldTag->getDeclContext(), SearchDC))) { @@ -17735,13 +17739,13 @@ Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK, SourceLocation KWLoc, // If this is a use of a previous tag, or if the tag is already declared // in the same scope (so that the definition/declaration completes or // rementions the tag), reuse the decl. - if (TUK == TUK_Reference || TUK == TUK_Friend || + if (TUK == TagUseKind::Reference || TUK == TagUseKind::Friend || isDeclInScope(DirectPrevDecl, SearchDC, S, SS.isNotEmpty() || isMemberSpecialization)) { // Make sure that this wasn't declared as an enum and now used as a // struct or something similar. if (!isAcceptableTagRedeclaration(PrevTagDecl, Kind, - TUK == TUK_Definition, KWLoc, + TUK == TagUseKind::Definition, KWLoc, Name)) { bool SafeToContinue = (PrevTagDecl->getTagKind() != TagTypeKind::Enum && @@ -17768,7 +17772,7 @@ Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK, SourceLocation KWLoc, if (Kind == TagTypeKind::Enum && PrevTagDecl->getTagKind() == TagTypeKind::Enum) { const EnumDecl *PrevEnum = cast(PrevTagDecl); - if (TUK == TUK_Reference || TUK == TUK_Friend) + if (TUK == TagUseKind::Reference || TUK == TagUseKind::Friend) return PrevTagDecl; QualType EnumUnderlyingTy; @@ -17783,14 +17787,14 @@ Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK, SourceLocation KWLoc, if (CheckEnumRedeclaration(NameLoc.isValid() ? NameLoc : KWLoc, ScopedEnum, EnumUnderlyingTy, IsFixed, PrevEnum)) - return TUK == TUK_Declaration ? PrevTagDecl : nullptr; + return TUK == TagUseKind::Declaration ? PrevTagDecl : nullptr; } // C++11 [class.mem]p1: // A member shall not be declared twice in the member-specification, // except that a nested class or member class template can be declared // and then later defined. - if (TUK == TUK_Declaration && PrevDecl->isCXXClassMember() && + if (TUK == TagUseKind::Declaration && PrevDecl->isCXXClassMember() && S->isDeclScope(PrevDecl)) { Diag(NameLoc, diag::ext_member_redeclared); Diag(PrevTagDecl->getLocation(), diag::note_previous_declaration); @@ -17799,11 +17803,11 @@ Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK, SourceLocation KWLoc, if (!Invalid) { // If this is a use, just return the declaration we found, unless // we have attributes. - if (TUK == TUK_Reference || TUK == TUK_Friend) { + if (TUK == TagUseKind::Reference || TUK == TagUseKind::Friend) { if (!Attrs.empty()) { // FIXME: Diagnose these attributes. For now, we create a new // declaration to hold them. - } else if (TUK == TUK_Reference && + } else if (TUK == TagUseKind::Reference && (PrevTagDecl->getFriendObjectKind() == Decl::FOK_Undeclared || PrevDecl->getOwningModule() != getCurrentModule()) && @@ -17827,7 +17831,7 @@ Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK, SourceLocation KWLoc, } // Diagnose attempts to redefine a tag. - if (TUK == TUK_Definition) { + if (TUK == TagUseKind::Definition) { if (NamedDecl *Def = PrevTagDecl->getDefinition()) { // If we're defining a specialization and the previous definition // is from an implicit instantiation, don't emit an error @@ -17907,7 +17911,7 @@ Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK, SourceLocation KWLoc, // Okay, we're going to make a redeclaration. If this is some kind // of reference, make sure we build the redeclaration in the same DC // as the original, and ignore the current access specifier. - if (TUK == TUK_Friend || TUK == TUK_Reference) { + if (TUK == TagUseKind::Friend || TUK == TagUseKind::Reference) { SearchDC = PrevTagDecl->getDeclContext(); AS = AS_none; } @@ -17933,7 +17937,7 @@ Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK, SourceLocation KWLoc, // Use a better diagnostic if an elaborated-type-specifier // found the wrong kind of type on the first // (non-redeclaration) lookup. - if ((TUK == TUK_Reference || TUK == TUK_Friend) && + if ((TUK == TagUseKind::Reference || TUK == TagUseKind::Friend) && !Previous.isForRedeclaration()) { NonTagKind NTK = getNonTagTypeDeclKind(PrevDecl, Kind); Diag(NameLoc, diag::err_tag_reference_non_tag) @@ -17947,7 +17951,7 @@ Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK, SourceLocation KWLoc, // do nothing // Diagnose implicit declarations introduced by elaborated types. - } else if (TUK == TUK_Reference || TUK == TUK_Friend) { + } else if (TUK == TagUseKind::Reference || TUK == TagUseKind::Friend) { NonTagKind NTK = getNonTagTypeDeclKind(PrevDecl, Kind); Diag(NameLoc, diag::err_tag_reference_conflict) << NTK; Diag(PrevDecl->getLocation(), diag::note_previous_decl) << PrevDecl; @@ -18006,7 +18010,7 @@ CreateNewDecl: StdAlignValT = cast(New); // If this is an undefined enum, warn. - if (TUK != TUK_Definition && !Invalid) { + if (TUK != TagUseKind::Definition && !Invalid) { TagDecl *Def; if (IsFixed && cast(New)->isFixed()) { // C++0x: 7.2p2: opaque-enum-declaration. @@ -18056,21 +18060,22 @@ CreateNewDecl: } // Only C23 and later allow defining new types in 'offsetof()'. - if (OOK != OOK_Outside && TUK == TUK_Definition && !getLangOpts().CPlusPlus && - !getLangOpts().C23) + if (OOK != OOK_Outside && TUK == TagUseKind::Definition && + !getLangOpts().CPlusPlus && !getLangOpts().C23) Diag(New->getLocation(), diag::ext_type_defined_in_offsetof) << (OOK == OOK_Macro) << New->getSourceRange(); // C++11 [dcl.type]p3: // A type-specifier-seq shall not define a class or enumeration [...]. if (!Invalid && getLangOpts().CPlusPlus && - (IsTypeSpecifier || IsTemplateParamOrArg) && TUK == TUK_Definition) { + (IsTypeSpecifier || IsTemplateParamOrArg) && + TUK == TagUseKind::Definition) { Diag(New->getLocation(), diag::err_type_defined_in_type_specifier) << Context.getTagDeclType(New); Invalid = true; } - if (!Invalid && getLangOpts().CPlusPlus && TUK == TUK_Definition && + if (!Invalid && getLangOpts().CPlusPlus && TUK == TagUseKind::Definition && DC->getDeclKind() == Decl::Enum) { Diag(New->getLocation(), diag::err_type_defined_in_enum) << Context.getTagDeclType(New); @@ -18082,7 +18087,7 @@ CreateNewDecl: if (SS.isSet()) { // If this is either a declaration or a definition, check the // nested-name-specifier against the current context. - if ((TUK == TUK_Definition || TUK == TUK_Declaration) && + if ((TUK == TagUseKind::Definition || TUK == TagUseKind::Declaration) && diagnoseQualifiedDeclaration(SS, DC, OrigName, Loc, /*TemplateId=*/nullptr, isMemberSpecialization)) @@ -18107,7 +18112,7 @@ CreateNewDecl: // many points during the parsing of a struct declaration (because // the #pragma tokens are effectively skipped over during the // parsing of the struct). - if (TUK == TUK_Definition && (!SkipBody || !SkipBody->ShouldSkip)) { + if (TUK == TagUseKind::Definition && (!SkipBody || !SkipBody->ShouldSkip)) { AddAlignmentAttributesForRecord(RD); AddMsStructLayoutForRecord(RD); } @@ -18138,7 +18143,7 @@ CreateNewDecl: if (getLangOpts().CPlusPlus) { // C++ [dcl.fct]p6: // Types shall not be defined in return or parameter types. - if (TUK == TUK_Definition && !IsTypeSpecifier) { + if (TUK == TagUseKind::Definition && !IsTypeSpecifier) { Diag(Loc, diag::err_type_defined_in_param_type) << Name; Invalid = true; @@ -18159,7 +18164,7 @@ CreateNewDecl: // In Microsoft mode, a friend declaration also acts as a forward // declaration so we always pass true to setObjectOfFriendDecl to make // the tag name visible. - if (TUK == TUK_Friend) + if (TUK == TagUseKind::Friend) New->setObjectOfFriendDecl(getLangOpts().MSVCCompat); // Set the access specifier. @@ -18169,14 +18174,14 @@ CreateNewDecl: if (PrevDecl) CheckRedeclarationInModule(New, PrevDecl); - if (TUK == TUK_Definition && (!SkipBody || !SkipBody->ShouldSkip)) + if (TUK == TagUseKind::Definition && (!SkipBody || !SkipBody->ShouldSkip)) New->startDefinition(); ProcessDeclAttributeList(S, New, Attrs); AddPragmaAttributes(S, New); // If this has an identifier, add it to the scope stack. - if (TUK == TUK_Friend) { + if (TUK == TagUseKind::Friend) { // We might be replacing an existing declaration in the lookup tables; // if so, borrow its access specifier. if (PrevDecl) diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp index 104e27139fe4..8ab429e2a136 100644 --- a/clang/lib/Sema/SemaDeclCXX.cpp +++ b/clang/lib/Sema/SemaDeclCXX.cpp @@ -17580,11 +17580,12 @@ DeclResult Sema::ActOnTemplatedFriendTag( if (Invalid) return true; - return CheckClassTemplate(S, TagSpec, TUK_Friend, TagLoc, SS, Name, - NameLoc, Attr, TemplateParams, AS_public, + return CheckClassTemplate(S, TagSpec, TagUseKind::Friend, TagLoc, SS, + Name, NameLoc, Attr, TemplateParams, AS_public, /*ModulePrivateLoc=*/SourceLocation(), FriendLoc, TempParamLists.size() - 1, - TempParamLists.data()).get(); + TempParamLists.data()) + .get(); } else { // The "template<>" header is extraneous. Diag(TemplateParams->getTemplateLoc(), diag::err_template_tag_noparams) @@ -17612,8 +17613,8 @@ DeclResult Sema::ActOnTemplatedFriendTag( if (SS.isEmpty()) { bool Owned = false; bool IsDependent = false; - return ActOnTag(S, TagSpec, TUK_Friend, TagLoc, SS, Name, NameLoc, Attr, - AS_public, + return ActOnTag(S, TagSpec, TagUseKind::Friend, TagLoc, SS, Name, NameLoc, + Attr, AS_public, /*ModulePrivateLoc=*/SourceLocation(), MultiTemplateParamsArg(), Owned, IsDependent, /*ScopedEnumKWLoc=*/SourceLocation(), @@ -17728,7 +17729,7 @@ Decl *Sema::ActOnFriendTypeDecl(Scope *S, const DeclSpec &DS, // Try to convert the decl specifier to a type. This works for // friend templates because ActOnTag never produces a ClassTemplateDecl - // for a TUK_Friend. + // for a TagUseKind::Friend. Declarator TheDeclarator(DS, ParsedAttributesView::none(), DeclaratorContext::Member); TypeSourceInfo *TSI = GetTypeForDeclarator(TheDeclarator); diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp index 02d9b64c2b14..8b82348754fa 100644 --- a/clang/lib/Sema/SemaTemplate.cpp +++ b/clang/lib/Sema/SemaTemplate.cpp @@ -1839,7 +1839,8 @@ DeclResult Sema::CheckClassTemplate( TemplateParameterList **OuterTemplateParamLists, SkipBodyInfo *SkipBody) { assert(TemplateParams && TemplateParams->size() > 0 && "No template parameters"); - assert(TUK != TUK_Reference && "Can only declare or define class templates"); + assert(TUK != TagUseKind::Reference && + "Can only declare or define class templates"); bool Invalid = false; // Check that we can declare a template here. @@ -1861,8 +1862,9 @@ DeclResult Sema::CheckClassTemplate( // C++11 [basic.lookup.elab]p2). DeclContext *SemanticContext; LookupResult Previous(*this, Name, NameLoc, - (SS.isEmpty() && TUK == TUK_Friend) - ? LookupTagName : LookupOrdinaryName, + (SS.isEmpty() && TUK == TagUseKind::Friend) + ? LookupTagName + : LookupOrdinaryName, forRedeclarationInCurContext()); if (SS.isNotEmpty() && !SS.isInvalid()) { SemanticContext = computeDeclContext(SS, true); @@ -1870,11 +1872,11 @@ DeclResult Sema::CheckClassTemplate( // FIXME: Horrible, horrible hack! We can't currently represent this // in the AST, and historically we have just ignored such friend // class templates, so don't complain here. - Diag(NameLoc, TUK == TUK_Friend + Diag(NameLoc, TUK == TagUseKind::Friend ? diag::warn_template_qualified_friend_ignored : diag::err_template_qualified_declarator_no_match) << SS.getScopeRep() << SS.getRange(); - return TUK != TUK_Friend; + return TUK != TagUseKind::Friend; } if (RequireCompleteDeclContext(SS, SemanticContext)) @@ -1889,7 +1891,7 @@ DeclResult Sema::CheckClassTemplate( Invalid = true; } - if (TUK != TUK_Friend && TUK != TUK_Reference) + if (TUK != TagUseKind::Friend && TUK != TagUseKind::Reference) diagnoseQualifiedDeclaration(SS, SemanticContext, Name, NameLoc, /*TemplateId-*/ nullptr, /*IsMemberSpecialization*/ false); @@ -1902,7 +1904,7 @@ DeclResult Sema::CheckClassTemplate( // If T is the name of a class, then each of the following shall have a // name different from T: // -- every member template of class T - if (TUK != TUK_Friend && + if (TUK != TagUseKind::Friend && DiagnoseClassNameShadow(SemanticContext, DeclarationNameInfo(Name, NameLoc))) return true; @@ -1944,7 +1946,7 @@ DeclResult Sema::CheckClassTemplate( } } - if (TUK == TUK_Friend) { + if (TUK == TagUseKind::Friend) { // C++ [namespace.memdef]p3: // [...] When looking for a prior declaration of a class or a function // declared as a friend, and when the name of the friend class or @@ -1981,9 +1983,8 @@ DeclResult Sema::CheckClassTemplate( PrevDecl = (*Previous.begin())->getUnderlyingDecl(); } } - } else if (PrevDecl && - !isDeclInScope(Previous.getRepresentativeDecl(), SemanticContext, - S, SS.isValid())) + } else if (PrevDecl && !isDeclInScope(Previous.getRepresentativeDecl(), + SemanticContext, S, SS.isValid())) PrevDecl = PrevClassTemplate = nullptr; if (auto *Shadow = dyn_cast_or_null( @@ -2005,7 +2006,7 @@ DeclResult Sema::CheckClassTemplate( // Ensure that the template parameter lists are compatible. Skip this check // for a friend in a dependent context: the template parameter list itself // could be dependent. - if (!(TUK == TUK_Friend && CurContext->isDependentContext()) && + if (!(TUK == TagUseKind::Friend && CurContext->isDependentContext()) && !TemplateParameterListsAreEqual( TemplateCompareNewDeclInfo(SemanticContext ? SemanticContext : CurContext, @@ -2021,8 +2022,8 @@ DeclResult Sema::CheckClassTemplate( // the class-key shall agree in kind with the original class // template declaration (7.1.5.3). RecordDecl *PrevRecordDecl = PrevClassTemplate->getTemplatedDecl(); - if (!isAcceptableTagRedeclaration(PrevRecordDecl, Kind, - TUK == TUK_Definition, KWLoc, Name)) { + if (!isAcceptableTagRedeclaration( + PrevRecordDecl, Kind, TUK == TagUseKind::Definition, KWLoc, Name)) { Diag(KWLoc, diag::err_use_with_wrong_tag) << Name << FixItHint::CreateReplacement(KWLoc, PrevRecordDecl->getKindName()); @@ -2031,7 +2032,7 @@ DeclResult Sema::CheckClassTemplate( } // Check for redefinition of this class template. - if (TUK == TUK_Definition) { + if (TUK == TagUseKind::Definition) { if (TagDecl *Def = PrevRecordDecl->getDefinition()) { // If we have a prior definition that is not visible, treat this as // simply making that previous definition visible. @@ -2068,7 +2069,7 @@ DeclResult Sema::CheckClassTemplate( // merging in the template parameter list from the previous class // template declaration. Skip this check for a friend in a dependent // context, because the template parameter list might be dependent. - if (!(TUK == TUK_Friend && CurContext->isDependentContext()) && + if (!(TUK == TagUseKind::Friend && CurContext->isDependentContext()) && CheckTemplateParameterList( TemplateParams, PrevClassTemplate ? GetTemplateParameterList(PrevClassTemplate) @@ -2076,8 +2077,8 @@ DeclResult Sema::CheckClassTemplate( (SS.isSet() && SemanticContext && SemanticContext->isRecord() && SemanticContext->isDependentContext()) ? TPC_ClassTemplateMember - : TUK == TUK_Friend ? TPC_FriendClassTemplate - : TPC_ClassTemplate, + : TUK == TagUseKind::Friend ? TPC_FriendClassTemplate + : TPC_ClassTemplate, SkipBody)) Invalid = true; @@ -2085,9 +2086,10 @@ DeclResult Sema::CheckClassTemplate( // If the name of the template was qualified, we must be defining the // template out-of-line. if (!SS.isInvalid() && !Invalid && !PrevClassTemplate) { - Diag(NameLoc, TUK == TUK_Friend ? diag::err_friend_decl_does_not_match - : diag::err_member_decl_does_not_match) - << Name << SemanticContext << /*IsDefinition*/true << SS.getRange(); + Diag(NameLoc, TUK == TagUseKind::Friend + ? diag::err_friend_decl_does_not_match + : diag::err_member_decl_does_not_match) + << Name << SemanticContext << /*IsDefinition*/ true << SS.getRange(); Invalid = true; } } @@ -2097,8 +2099,8 @@ DeclResult Sema::CheckClassTemplate( // recent declaration tricking the template instantiator to make substitutions // there. // FIXME: Figure out how to combine with shouldLinkDependentDeclWithPrevious - bool ShouldAddRedecl - = !(TUK == TUK_Friend && CurContext->isDependentContext()); + bool ShouldAddRedecl = + !(TUK == TagUseKind::Friend && CurContext->isDependentContext()); CXXRecordDecl *NewClass = CXXRecordDecl::Create(Context, Kind, SemanticContext, KWLoc, NameLoc, Name, @@ -2113,7 +2115,7 @@ DeclResult Sema::CheckClassTemplate( // Add alignment attributes if necessary; these attributes are checked when // the ASTContext lays out the structure. - if (TUK == TUK_Definition && (!SkipBody || !SkipBody->ShouldSkip)) { + if (TUK == TagUseKind::Definition && (!SkipBody || !SkipBody->ShouldSkip)) { AddAlignmentAttributesForRecord(NewClass); AddMsStructLayoutForRecord(NewClass); } @@ -2144,14 +2146,15 @@ DeclResult Sema::CheckClassTemplate( PrevClassTemplate->setMemberSpecialization(); // Set the access specifier. - if (!Invalid && TUK != TUK_Friend && NewTemplate->getDeclContext()->isRecord()) + if (!Invalid && TUK != TagUseKind::Friend && + NewTemplate->getDeclContext()->isRecord()) SetMemberAccessSpecifier(NewTemplate, PrevClassTemplate, AS); // Set the lexical context of these templates NewClass->setLexicalDeclContext(CurContext); NewTemplate->setLexicalDeclContext(CurContext); - if (TUK == TUK_Definition && (!SkipBody || !SkipBody->ShouldSkip)) + if (TUK == TagUseKind::Definition && (!SkipBody || !SkipBody->ShouldSkip)) NewClass->startDefinition(); ProcessDeclAttributeList(S, NewClass, Attr); @@ -2164,7 +2167,7 @@ DeclResult Sema::CheckClassTemplate( inferGslOwnerPointerAttribute(NewClass); inferNullableClassAttribute(NewClass); - if (TUK != TUK_Friend) { + if (TUK != TagUseKind::Friend) { // Per C++ [basic.scope.temp]p2, skip the template parameter scopes. Scope *Outer = S; while ((Outer->getFlags() & Scope::TemplateParamScope) != 0) @@ -5015,7 +5018,7 @@ TypeResult Sema::ActOnTagTemplateIdType(TagUseKind TUK, IdentifierInfo *Id = D->getIdentifier(); assert(Id && "templated class must have an identifier"); - if (!isAcceptableTagRedeclaration(D, TagKind, TUK == TUK_Definition, + if (!isAcceptableTagRedeclaration(D, TagKind, TUK == TagUseKind::Definition, TagLoc, Id)) { Diag(TagLoc, diag::err_use_with_wrong_tag) << Result @@ -9451,7 +9454,7 @@ DeclResult Sema::ActOnClassTemplateSpecialization( SourceLocation ModulePrivateLoc, CXXScopeSpec &SS, TemplateIdAnnotation &TemplateId, const ParsedAttributesView &Attr, MultiTemplateParamsArg TemplateParameterLists, SkipBodyInfo *SkipBody) { - assert(TUK != TUK_Reference && "References are not specializations"); + assert(TUK != TagUseKind::Reference && "References are not specializations"); SourceLocation TemplateNameLoc = TemplateId.TemplateNameLoc; SourceLocation LAngleLoc = TemplateId.LAngleLoc; @@ -9473,7 +9476,7 @@ DeclResult Sema::ActOnClassTemplateSpecialization( bool isPartialSpecialization = false; if (SS.isSet()) { - if (TUK != TUK_Reference && TUK != TUK_Friend && + if (TUK != TagUseKind::Reference && TUK != TagUseKind::Friend && diagnoseQualifiedDeclaration(SS, ClassTemplate->getDeclContext(), ClassTemplate->getDeclName(), TemplateNameLoc, &TemplateId, @@ -9488,9 +9491,8 @@ DeclResult Sema::ActOnClassTemplateSpecialization( bool Invalid = false; TemplateParameterList *TemplateParams = MatchTemplateParametersToScopeSpecifier( - KWLoc, TemplateNameLoc, SS, &TemplateId, - TemplateParameterLists, TUK == TUK_Friend, isMemberSpecialization, - Invalid); + KWLoc, TemplateNameLoc, SS, &TemplateId, TemplateParameterLists, + TUK == TagUseKind::Friend, isMemberSpecialization, Invalid); if (Invalid) return true; @@ -9501,7 +9503,7 @@ DeclResult Sema::ActOnClassTemplateSpecialization( if (TemplateParams && TemplateParams->size() > 0) { isPartialSpecialization = true; - if (TUK == TUK_Friend) { + if (TUK == TagUseKind::Friend) { Diag(KWLoc, diag::err_partial_specialization_friend) << SourceRange(LAngleLoc, RAngleLoc); return true; @@ -9537,14 +9539,15 @@ DeclResult Sema::ActOnClassTemplateSpecialization( } } } else if (TemplateParams) { - if (TUK == TUK_Friend) + if (TUK == TagUseKind::Friend) Diag(KWLoc, diag::err_template_spec_friend) << FixItHint::CreateRemoval( SourceRange(TemplateParams->getTemplateLoc(), TemplateParams->getRAngleLoc())) << SourceRange(LAngleLoc, RAngleLoc); } else { - assert(TUK == TUK_Friend && "should have a 'template<>' for this decl"); + assert(TUK == TagUseKind::Friend && + "should have a 'template<>' for this decl"); } // Check that the specialization uses the same tag kind as the @@ -9552,8 +9555,8 @@ DeclResult Sema::ActOnClassTemplateSpecialization( TagTypeKind Kind = TypeWithKeyword::getTagTypeKindForTypeSpec(TagSpec); assert(Kind != TagTypeKind::Enum && "Invalid enum tag in class template spec!"); - if (!isAcceptableTagRedeclaration(ClassTemplate->getTemplatedDecl(), - Kind, TUK == TUK_Definition, KWLoc, + if (!isAcceptableTagRedeclaration(ClassTemplate->getTemplatedDecl(), Kind, + TUK == TagUseKind::Definition, KWLoc, ClassTemplate->getIdentifier())) { Diag(KWLoc, diag::err_use_with_wrong_tag) << ClassTemplate @@ -9617,7 +9620,7 @@ DeclResult Sema::ActOnClassTemplateSpecialization( // Check whether we can declare a class template specialization in // the current scope. - if (TUK != TUK_Friend && + if (TUK != TagUseKind::Friend && CheckTemplateSpecializationScope(*this, ClassTemplate, PrevDecl, TemplateNameLoc, isPartialSpecialization)) @@ -9644,8 +9647,8 @@ DeclResult Sema::ActOnClassTemplateSpecialization( // This rule has since been removed, because it's redundant given DR1495, // but we keep it because it produces better diagnostics and recovery. Diag(TemplateNameLoc, diag::err_partial_spec_args_match_primary_template) - << /*class template*/0 << (TUK == TUK_Definition) - << FixItHint::CreateRemoval(SourceRange(LAngleLoc, RAngleLoc)); + << /*class template*/ 0 << (TUK == TagUseKind::Definition) + << FixItHint::CreateRemoval(SourceRange(LAngleLoc, RAngleLoc)); return CheckClassTemplate(S, TagSpec, TUK, KWLoc, SS, ClassTemplate->getIdentifier(), TemplateNameLoc, @@ -9737,11 +9740,11 @@ DeclResult Sema::ActOnClassTemplateSpecialization( } // If this is not a friend, note that this is an explicit specialization. - if (TUK != TUK_Friend) + if (TUK != TagUseKind::Friend) Specialization->setSpecializationKind(TSK_ExplicitSpecialization); // Check that this isn't a redefinition of this specialization. - if (TUK == TUK_Definition) { + if (TUK == TagUseKind::Definition) { RecordDecl *Def = Specialization->getDefinition(); NamedDecl *Hidden = nullptr; if (Def && SkipBody && !hasVisibleDefinition(Def, &Hidden)) { @@ -9762,7 +9765,7 @@ DeclResult Sema::ActOnClassTemplateSpecialization( // Add alignment attributes if necessary; these attributes are checked when // the ASTContext lays out the structure. - if (TUK == TUK_Definition && (!SkipBody || !SkipBody->ShouldSkip)) { + if (TUK == TagUseKind::Definition && (!SkipBody || !SkipBody->ShouldSkip)) { AddAlignmentAttributesForRecord(Specialization); AddMsStructLayoutForRecord(Specialization); } @@ -9783,10 +9786,10 @@ DeclResult Sema::ActOnClassTemplateSpecialization( Specialization->setLexicalDeclContext(CurContext); // We may be starting the definition of this specialization. - if (TUK == TUK_Definition && (!SkipBody || !SkipBody->ShouldSkip)) + if (TUK == TagUseKind::Definition && (!SkipBody || !SkipBody->ShouldSkip)) Specialization->startDefinition(); - if (TUK == TUK_Friend) { + if (TUK == TagUseKind::Friend) { // Build the fully-sugared type for this class template // specialization as the user wrote in the specialization // itself. This means that we'll pretty-print the type retrieved @@ -11160,11 +11163,13 @@ Sema::ActOnExplicitInstantiation(Scope *S, SourceLocation ExternLoc, bool Owned = false; bool IsDependent = false; - Decl *TagD = ActOnTag(S, TagSpec, Sema::TUK_Reference, KWLoc, SS, Name, - NameLoc, Attr, AS_none, /*ModulePrivateLoc=*/SourceLocation(), + Decl *TagD = + ActOnTag(S, TagSpec, TagUseKind::Reference, KWLoc, SS, Name, NameLoc, + Attr, AS_none, /*ModulePrivateLoc=*/SourceLocation(), MultiTemplateParamsArg(), Owned, IsDependent, SourceLocation(), false, TypeResult(), /*IsTypeSpecifier*/ false, - /*IsTemplateParamOrArg*/ false, /*OOK=*/OOK_Outside).get(); + /*IsTemplateParamOrArg*/ false, /*OOK=*/OOK_Outside) + .get(); assert(!IsDependent && "explicit instantiation of dependent name not yet handled"); if (!TagD) @@ -11695,9 +11700,9 @@ TypeResult Sema::ActOnDependentTag(Scope *S, unsigned TagSpec, TagUseKind TUK, TagTypeKind Kind = TypeWithKeyword::getTagTypeKindForTypeSpec(TagSpec); - if (TUK == TUK_Declaration || TUK == TUK_Definition) { + if (TUK == TagUseKind::Declaration || TUK == TagUseKind::Definition) { Diag(NameLoc, diag::err_dependent_tag_decl) - << (TUK == TUK_Definition) << llvm::to_underlying(Kind) + << (TUK == TagUseKind::Definition) << llvm::to_underlying(Kind) << SS.getRange(); return true; } -- GitLab From 0012b1ea84e671a9e0c9f7f2d1564315ed9cbcca Mon Sep 17 00:00:00 2001 From: Louis Dionne Date: Tue, 21 May 2024 15:08:47 -0700 Subject: [PATCH 043/452] [libc++] Refactor flaky tests for std::shared_lock (#91779) This makes the tests non-flaky. --- .../thread.lock.shared.cons/mutex.pass.cpp | 132 ++++++++--------- .../thread.lock.shared.locking/lock.pass.cpp | 140 +++++++++++------- .../try_lock.pass.cpp | 135 ++++++++++++----- 3 files changed, 242 insertions(+), 165 deletions(-) diff --git a/libcxx/test/std/thread/thread.mutex/thread.lock/thread.lock.shared/thread.lock.shared.cons/mutex.pass.cpp b/libcxx/test/std/thread/thread.mutex/thread.lock/thread.lock.shared/thread.lock.shared.cons/mutex.pass.cpp index 4940041bcf96..ece330134f2c 100644 --- a/libcxx/test/std/thread/thread.mutex/thread.lock/thread.lock.shared/thread.lock.shared.cons/mutex.pass.cpp +++ b/libcxx/test/std/thread/thread.mutex/thread.lock/thread.lock.shared/thread.lock.shared.cons/mutex.pass.cpp @@ -5,10 +5,9 @@ // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// -// + // UNSUPPORTED: no-threads // UNSUPPORTED: c++03, c++11 -// ALLOW_RETRIES: 2 // @@ -19,9 +18,8 @@ // template shared_lock(shared_lock<_Mutex>) // -> shared_lock<_Mutex>; // C++17 +#include #include -#include -#include #include #include #include @@ -29,77 +27,77 @@ #include "make_test_thread.h" #include "test_macros.h" -typedef std::chrono::system_clock Clock; -typedef Clock::time_point time_point; -typedef Clock::duration duration; -typedef std::chrono::milliseconds ms; -typedef std::chrono::nanoseconds ns; - -ms WaitTime = ms(250); - -// Thread sanitizer causes more overhead and will sometimes cause this test -// to fail. To prevent this we give Thread sanitizer more time to complete the -// test. -#if !defined(TEST_IS_EXECUTED_IN_A_SLOW_ENVIRONMENT) -ms Tolerance = ms(50); -#else -ms Tolerance = ms(50 * 5); -#endif +struct Monitor { + bool lock_shared_called = false; + bool unlock_shared_called = false; +}; -std::shared_timed_mutex m; +struct TrackedMutex { + Monitor* monitor = nullptr; -void f() -{ - time_point t0 = Clock::now(); - time_point t1; - { - std::shared_lock ul(m); - t1 = Clock::now(); - } - ns d = t1 - t0 - WaitTime; - assert(d < Tolerance); // within tolerance -} + void lock_shared() { + if (monitor != nullptr) + monitor->lock_shared_called = true; + } + void unlock_shared() { + if (monitor != nullptr) + monitor->unlock_shared_called = true; + } +}; -void g() -{ - time_point t0 = Clock::now(); - time_point t1; - { - std::shared_lock ul(m); - t1 = Clock::now(); - } - ns d = t1 - t0; - assert(d < Tolerance); // within tolerance -} +template +void test() { + // Basic sanity test + { + Mutex mutex; + std::vector threads; + std::atomic ready(false); + for (int i = 0; i != 5; ++i) { + threads.push_back(support::make_test_thread([&] { + while (!ready) { + // spin + } -int main(int, char**) -{ - std::vector v; - { - m.lock(); - for (int i = 0; i < 5; ++i) - v.push_back(support::make_test_thread(f)); - std::this_thread::sleep_for(WaitTime); - m.unlock(); - for (auto& t : v) - t.join(); - } - { - m.lock_shared(); - for (auto& t : v) - t = support::make_test_thread(g); - std::thread q = support::make_test_thread(f); - std::this_thread::sleep_for(WaitTime); - m.unlock_shared(); - for (auto& t : v) - t.join(); - q.join(); + std::shared_lock lock(mutex); + assert(lock.owns_lock()); + })); } + ready = true; + for (auto& t : threads) + t.join(); + } + + // Test CTAD + { +#if TEST_STD_VER >= 17 + Mutex mutex; + std::shared_lock lock(mutex); + static_assert(std::is_same>::value); +#endif + } +} + +int main(int, char**) { #if TEST_STD_VER >= 17 - std::shared_lock sl(m); - static_assert((std::is_same>::value), "" ); + test(); #endif + test(); + test(); + + // Use shared_lock with a dummy mutex class that tracks whether each + // operation has been called or not. + { + Monitor monitor; + TrackedMutex mutex{&monitor}; + + std::shared_lock lock(mutex); + assert(monitor.lock_shared_called); + assert(lock.owns_lock()); + + lock.unlock(); + assert(monitor.unlock_shared_called); + } return 0; } diff --git a/libcxx/test/std/thread/thread.mutex/thread.lock/thread.lock.shared/thread.lock.shared.locking/lock.pass.cpp b/libcxx/test/std/thread/thread.mutex/thread.lock/thread.lock.shared/thread.lock.shared.locking/lock.pass.cpp index edb7c42356ac..d36ca1d38f8f 100644 --- a/libcxx/test/std/thread/thread.mutex/thread.lock/thread.lock.shared/thread.lock.shared.locking/lock.pass.cpp +++ b/libcxx/test/std/thread/thread.mutex/thread.lock/thread.lock.shared/thread.lock.shared.locking/lock.pass.cpp @@ -5,10 +5,9 @@ // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// -// + // UNSUPPORTED: no-threads // UNSUPPORTED: c++03, c++11 -// ALLOW_RETRIES: 2 // @@ -16,10 +15,9 @@ // void lock(); +#include #include -#include -#include -#include +#include // std::defer_lock #include #include #include @@ -28,71 +26,99 @@ #include "make_test_thread.h" #include "test_macros.h" -std::shared_timed_mutex m; +struct Monitor { + bool lock_shared_called = false; + bool unlock_shared_called = false; +}; -typedef std::chrono::system_clock Clock; -typedef Clock::time_point time_point; -typedef Clock::duration duration; -typedef std::chrono::milliseconds ms; -typedef std::chrono::nanoseconds ns; +struct TrackedMutex { + Monitor* monitor = nullptr; -ms WaitTime = ms(250); + void lock_shared() { + if (monitor != nullptr) + monitor->lock_shared_called = true; + } + void unlock_shared() { + if (monitor != nullptr) + monitor->unlock_shared_called = true; + } +}; -// Thread sanitizer causes more overhead and will sometimes cause this test -// to fail. To prevent this we give Thread sanitizer more time to complete the -// test. -#if !defined(TEST_IS_EXECUTED_IN_A_SLOW_ENVIRONMENT) -ms Tolerance = ms(25); -#else -ms Tolerance = ms(25 * 5); -#endif +template +void test() { + // Basic sanity test + { + Mutex mutex; + std::vector threads; + std::atomic ready(false); + for (int i = 0; i != 5; ++i) { + threads.push_back(support::make_test_thread([&] { + while (!ready) { + // spin + } + std::shared_lock lock(mutex, std::defer_lock); + lock.lock(); + assert(lock.owns_lock()); + })); + } + + ready = true; + for (auto& t : threads) + t.join(); + } -void f() -{ - std::shared_lock lk(m, std::defer_lock); - time_point t0 = Clock::now(); - lk.lock(); - time_point t1 = Clock::now(); - assert(lk.owns_lock() == true); - ns d = t1 - t0 - WaitTime; - assert(d < Tolerance); // within tolerance + // Try locking the same shared_lock again in the same thread. This should throw an exception. + { + Mutex mutex; + std::shared_lock lock(mutex, std::defer_lock); + lock.lock(); + assert(lock.owns_lock()); #ifndef TEST_HAS_NO_EXCEPTIONS - try - { - lk.lock(); - assert(false); - } - catch (std::system_error& e) - { - assert(e.code().value() == EDEADLK); + try { + lock.lock(); + assert(false); + } catch (std::system_error const& e) { + assert(e.code() == std::errc::resource_deadlock_would_occur); } #endif - lk.unlock(); - lk.release(); + } + + // Try locking a shared_lock that isn't associated to any mutex. This should throw an exception. + { + std::shared_lock lock; // no associated mutex #ifndef TEST_HAS_NO_EXCEPTIONS - try - { - lk.lock(); - assert(false); - } - catch (std::system_error& e) - { - assert(e.code().value() == EPERM); + try { + lock.lock(); + assert(false); + } catch (std::system_error const& e) { + assert(e.code() == std::errc::operation_not_permitted); } #endif + } } -int main(int, char**) -{ - m.lock(); - std::vector v; - for (int i = 0; i < 5; ++i) - v.push_back(support::make_test_thread(f)); - std::this_thread::sleep_for(WaitTime); - m.unlock(); - for (auto& t : v) - t.join(); +int main(int, char**) { +#if TEST_STD_VER >= 17 + test(); +#endif + test(); + test(); + + // Use shared_lock with a dummy mutex class that tracks whether each + // operation has been called or not. + { + Monitor monitor; + TrackedMutex mutex{&monitor}; + + std::shared_lock lock(mutex, std::defer_lock); + lock.lock(); + assert(monitor.lock_shared_called); + assert(lock.owns_lock()); + + lock.unlock(); + assert(monitor.unlock_shared_called); + } return 0; } diff --git a/libcxx/test/std/thread/thread.mutex/thread.lock/thread.lock.shared/thread.lock.shared.locking/try_lock.pass.cpp b/libcxx/test/std/thread/thread.mutex/thread.lock/thread.lock.shared/thread.lock.shared.locking/try_lock.pass.cpp index 0e707fcf2d50..b6146680b6e3 100644 --- a/libcxx/test/std/thread/thread.mutex/thread.lock/thread.lock.shared/thread.lock.shared.locking/try_lock.pass.cpp +++ b/libcxx/test/std/thread/thread.mutex/thread.lock/thread.lock.shared/thread.lock.shared.locking/try_lock.pass.cpp @@ -5,11 +5,9 @@ // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// -// + // UNSUPPORTED: no-threads // UNSUPPORTED: c++03, c++11 -// -// ALLOW_RETRIES: 2 // @@ -17,60 +15,115 @@ // bool try_lock(); +#include #include -#include +#include // std::defer_lock #include #include +#include +#include +#include "make_test_thread.h" #include "test_macros.h" -bool try_lock_called = false; +struct Monitor { + bool try_lock_shared_called = false; + bool unlock_shared_called = false; +}; -struct mutex -{ - bool try_lock_shared() - { - try_lock_called = !try_lock_called; - return try_lock_called; - } - void unlock_shared() {} +struct TrackedMutex { + Monitor* monitor = nullptr; + + bool try_lock_shared() { + if (monitor != nullptr) + monitor->try_lock_shared_called = true; + return true; + } + void unlock_shared() { + if (monitor != nullptr) + monitor->unlock_shared_called = true; + } }; -mutex m; +template +void test() { + // Basic sanity test + { + Mutex mutex; + std::vector threads; + std::atomic ready(false); + for (int i = 0; i != 5; ++i) { + threads.push_back(support::make_test_thread([&] { + while (!ready) { + // spin + } -int main(int, char**) -{ - std::shared_lock lk(m, std::defer_lock); - assert(lk.try_lock() == true); - assert(try_lock_called == true); - assert(lk.owns_lock() == true); -#ifndef TEST_HAS_NO_EXCEPTIONS - try - { - TEST_IGNORE_NODISCARD lk.try_lock(); - assert(false); + std::shared_lock lock(mutex, std::defer_lock); + bool result = lock.try_lock(); + assert(result); + assert(lock.owns_lock()); + })); } - catch (std::system_error& e) - { - assert(e.code().value() == EDEADLK); + + ready = true; + for (auto& t : threads) + t.join(); + } + + // Make sure that we throw an exception if we try to re-lock a mutex that is + // already locked by the current thread. + { + Mutex mutex; + + std::shared_lock lock(mutex, std::defer_lock); + assert(lock.try_lock()); + assert(lock.owns_lock()); +#ifndef TEST_HAS_NO_EXCEPTIONS + try { + TEST_IGNORE_NODISCARD lock.try_lock(); + assert(false); + } catch (std::system_error const& e) { + assert(e.code() == std::errc::resource_deadlock_would_occur); } #endif - lk.unlock(); - assert(lk.try_lock() == false); - assert(try_lock_called == false); - assert(lk.owns_lock() == false); - lk.release(); + } + + // Make sure that we throw an exception if we try to lock a shared_lock + // that is not associated to any mutex. + { + std::shared_lock lock; // not associated to a mutex #ifndef TEST_HAS_NO_EXCEPTIONS - try - { - TEST_IGNORE_NODISCARD lk.try_lock(); - assert(false); - } - catch (std::system_error& e) - { - assert(e.code().value() == EPERM); + try { + TEST_IGNORE_NODISCARD lock.try_lock(); + assert(false); + } catch (std::system_error const& e) { + assert(e.code() == std::errc::operation_not_permitted); } #endif + } +} + +int main(int, char**) { +#if TEST_STD_VER >= 17 + test(); +#endif + test(); + test(); + + // Use shared_lock with a dummy mutex class that tracks whether each + // operation has been called or not. + { + Monitor monitor; + TrackedMutex mutex{&monitor}; + + std::shared_lock lock(mutex, std::defer_lock); + bool result = lock.try_lock(); + assert(result); + assert(monitor.try_lock_shared_called); + assert(lock.owns_lock()); + lock.unlock(); + assert(monitor.unlock_shared_called); + } return 0; } -- GitLab From f6ff87dd90074b694e420d93389c749189bca0ec Mon Sep 17 00:00:00 2001 From: Heejin Ahn Date: Tue, 21 May 2024 15:43:08 -0700 Subject: [PATCH 044/452] [libunwind][WebAssembly] Make libunwind compilable (#92192) This tries to make Wasm compilable in LLVM tree with CMake for non-Emscripten platform. This - Adds `-D__USING_WASM_EXCEPTIONS__` when you compile with `-fwasm-exceptions` (like other EH options) in Clang - Exclude `UnwindLevel1.c`, `UnwindRegistersSave.S`, and `UnwindRegistersRestore.S` when compiling with Wasm - Changed some `__USING_WASM_EXCEPTIONS__` to `__wasm__`; they should be applied when compiling with Wasm w/o exceptions. - Define some unused macros to make it compile Fixes #72771. --- libunwind/include/__libunwind_config.h | 4 ++++ libunwind/src/UnwindLevel1.c | 3 ++- libunwind/src/UnwindRegistersRestore.S | 4 ++-- libunwind/src/UnwindRegistersSave.S | 4 ++-- libunwind/src/libunwind.cpp | 4 ++-- 5 files changed, 12 insertions(+), 7 deletions(-) diff --git a/libunwind/include/__libunwind_config.h b/libunwind/include/__libunwind_config.h index 8db336b2d727..028b9e3baa80 100644 --- a/libunwind/include/__libunwind_config.h +++ b/libunwind/include/__libunwind_config.h @@ -180,6 +180,10 @@ #endif #define _LIBUNWIND_HIGHEST_DWARF_REGISTER \ _LIBUNWIND_HIGHEST_DWARF_REGISTER_LOONGARCH +#elif defined(__wasm__) +// Unused +#define _LIBUNWIND_CONTEXT_SIZE 0 +#define _LIBUNWIND_CURSOR_SIZE 0 # else # error "Unsupported architecture." # endif diff --git a/libunwind/src/UnwindLevel1.c b/libunwind/src/UnwindLevel1.c index 05d0f2cb0a0a..48e7bc3b9e00 100644 --- a/libunwind/src/UnwindLevel1.c +++ b/libunwind/src/UnwindLevel1.c @@ -31,7 +31,8 @@ #include "libunwind_ext.h" #include "unwind.h" -#if !defined(_LIBUNWIND_ARM_EHABI) && !defined(__USING_SJLJ_EXCEPTIONS__) +#if !defined(_LIBUNWIND_ARM_EHABI) && !defined(__USING_SJLJ_EXCEPTIONS__) && \ + !defined(__wasm__) #ifndef _LIBUNWIND_SUPPORT_SEH_UNWIND diff --git a/libunwind/src/UnwindRegistersRestore.S b/libunwind/src/UnwindRegistersRestore.S index 42c2488fc7cf..67d9e0571189 100644 --- a/libunwind/src/UnwindRegistersRestore.S +++ b/libunwind/src/UnwindRegistersRestore.S @@ -20,7 +20,7 @@ .text #endif -#if !defined(__USING_SJLJ_EXCEPTIONS__) +#if !defined(__USING_SJLJ_EXCEPTIONS__) && !defined(__wasm__) #if defined(__i386__) DEFINE_LIBUNWIND_FUNCTION(__libunwind_Registers_x86_jumpto) @@ -1232,7 +1232,7 @@ DEFINE_LIBUNWIND_FUNCTION(_ZN9libunwind19Registers_loongarch6jumptoEv) #endif -#endif /* !defined(__USING_SJLJ_EXCEPTIONS__) */ +#endif /* !defined(__USING_SJLJ_EXCEPTIONS__) && !defined(__wasm__) */ NO_EXEC_STACK_DIRECTIVE diff --git a/libunwind/src/UnwindRegistersSave.S b/libunwind/src/UnwindRegistersSave.S index 19a0e87d683c..5bf6055fe414 100644 --- a/libunwind/src/UnwindRegistersSave.S +++ b/libunwind/src/UnwindRegistersSave.S @@ -20,7 +20,7 @@ .text #endif -#if !defined(__USING_SJLJ_EXCEPTIONS__) +#if !defined(__USING_SJLJ_EXCEPTIONS__) && !defined(__wasm__) #if defined(__i386__) @@ -1177,6 +1177,6 @@ DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext) WEAK_ALIAS(__unw_getcontext, unw_getcontext) -#endif /* !defined(__USING_SJLJ_EXCEPTIONS__) */ +#endif /* !defined(__USING_SJLJ_EXCEPTIONS__) && !defined(__wasm__) */ NO_EXEC_STACK_DIRECTIVE diff --git a/libunwind/src/libunwind.cpp b/libunwind/src/libunwind.cpp index 217dde909863..7e5c6bd263e1 100644 --- a/libunwind/src/libunwind.cpp +++ b/libunwind/src/libunwind.cpp @@ -26,7 +26,7 @@ #include #endif -#if !defined(__USING_SJLJ_EXCEPTIONS__) && !defined(__USING_WASM_EXCEPTIONS__) +#if !defined(__USING_SJLJ_EXCEPTIONS__) && !defined(__wasm__) #include "AddressSpace.hpp" #include "UnwindCursor.hpp" @@ -348,7 +348,7 @@ void __unw_remove_dynamic_eh_frame_section(unw_word_t eh_frame_start) { #endif // defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) #endif // !defined(__USING_SJLJ_EXCEPTIONS__) && - // !defined(__USING_WASM_EXCEPTIONS__) + // !defined(__wasm__) #ifdef __APPLE__ -- GitLab From b3e71ec9f7efe15f7fd3dd4fc398860e1e857c11 Mon Sep 17 00:00:00 2001 From: Petr Hosek Date: Tue, 21 May 2024 15:46:04 -0700 Subject: [PATCH 045/452] [libc] Provide __libc_{init,fini}_array for baremetal (#90828) These are provided by newlib and many baremetal projects assume they're available rather than providing their own implementation. --- libc/cmake/modules/LLVMLibCObjectRules.cmake | 3 -- libc/config/baremetal/arm/entrypoints.txt | 4 +++ libc/config/baremetal/riscv/entrypoints.txt | 4 +++ libc/startup/baremetal/CMakeLists.txt | 11 +++++++ libc/startup/baremetal/fini.cpp | 27 +++++++++++++++++ libc/startup/baremetal/init.cpp | 32 ++++++++++++++++++++ 6 files changed, 78 insertions(+), 3 deletions(-) create mode 100644 libc/startup/baremetal/CMakeLists.txt create mode 100644 libc/startup/baremetal/fini.cpp create mode 100644 libc/startup/baremetal/init.cpp diff --git a/libc/cmake/modules/LLVMLibCObjectRules.cmake b/libc/cmake/modules/LLVMLibCObjectRules.cmake index 0649e9f7a767..134c5143d6d6 100644 --- a/libc/cmake/modules/LLVMLibCObjectRules.cmake +++ b/libc/cmake/modules/LLVMLibCObjectRules.cmake @@ -246,9 +246,6 @@ function(create_entrypoint_object fq_target_name) if(NOT ADD_ENTRYPOINT_OBJ_SRCS) message(FATAL_ERROR "`add_entrypoint_object` rule requires SRCS to be specified.") endif() - if(NOT ADD_ENTRYPOINT_OBJ_HDRS) - message(FATAL_ERROR "`add_entrypoint_object` rule requires HDRS to be specified.") - endif() if(NOT ADD_ENTRYPOINT_OBJ_CXX_STANDARD) set(ADD_ENTRYPOINT_OBJ_CXX_STANDARD ${CMAKE_CXX_STANDARD}) endif() diff --git a/libc/config/baremetal/arm/entrypoints.txt b/libc/config/baremetal/arm/entrypoints.txt index 4e3d1cb9f533..7fb82c60a1bb 100644 --- a/libc/config/baremetal/arm/entrypoints.txt +++ b/libc/config/baremetal/arm/entrypoints.txt @@ -183,6 +183,10 @@ set(TARGET_LIBC_ENTRYPOINTS # time.h entrypoints libc.src.time.difftime + + # internal entrypoints + libc.startup.baremetal.init + libc.startup.baremetal.fini ) set(TARGET_LIBM_ENTRYPOINTS diff --git a/libc/config/baremetal/riscv/entrypoints.txt b/libc/config/baremetal/riscv/entrypoints.txt index 7efd9bcd5b3c..b769b43f03a2 100644 --- a/libc/config/baremetal/riscv/entrypoints.txt +++ b/libc/config/baremetal/riscv/entrypoints.txt @@ -183,6 +183,10 @@ set(TARGET_LIBC_ENTRYPOINTS # time.h entrypoints libc.src.time.difftime + + # internal entrypoints + libc.startup.baremetal.init + libc.startup.baremetal.fini ) set(TARGET_LIBM_ENTRYPOINTS diff --git a/libc/startup/baremetal/CMakeLists.txt b/libc/startup/baremetal/CMakeLists.txt new file mode 100644 index 000000000000..4faced93fabe --- /dev/null +++ b/libc/startup/baremetal/CMakeLists.txt @@ -0,0 +1,11 @@ +add_entrypoint_object( + init + SRCS + init.cpp +) + +add_entrypoint_object( + fini + SRCS + fini.cpp +) diff --git a/libc/startup/baremetal/fini.cpp b/libc/startup/baremetal/fini.cpp new file mode 100644 index 000000000000..84997fb4fa1d --- /dev/null +++ b/libc/startup/baremetal/fini.cpp @@ -0,0 +1,27 @@ +//===-- Implementation file of __libc_fini_array --------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +#include +#include + +extern "C" { +extern uintptr_t __fini_array_start[]; +extern uintptr_t __fini_array_end[]; +} + +namespace LIBC_NAMESPACE { + +using FiniCallback = void(void); + +extern "C" void __libc_fini_array(void) { + size_t fini_array_size = __fini_array_end - __fini_array_start; + for (size_t i = fini_array_size; i > 0; --i) + reinterpret_cast(__fini_array_start[i - 1])(); +} + +} // namespace LIBC_NAMESPACE diff --git a/libc/startup/baremetal/init.cpp b/libc/startup/baremetal/init.cpp new file mode 100644 index 000000000000..08dff74f0519 --- /dev/null +++ b/libc/startup/baremetal/init.cpp @@ -0,0 +1,32 @@ +//===-- Implementation file of __libc_init_array --------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +#include +#include + +extern "C" { +extern uintptr_t __preinit_array_start[]; +extern uintptr_t __preinit_array_end[]; +extern uintptr_t __init_array_start[]; +extern uintptr_t __init_array_end[]; +} + +namespace LIBC_NAMESPACE { + +using InitCallback = void(void); + +extern "C" void __libc_init_array(void) { + size_t preinit_array_size = __preinit_array_end - __preinit_array_start; + for (size_t i = 0; i < preinit_array_size; ++i) + reinterpret_cast(__preinit_array_start[i])(); + size_t init_array_size = __init_array_end - __init_array_start; + for (size_t i = 0; i < init_array_size; ++i) + reinterpret_cast(__init_array_start[i])(); +} + +} // namespace LIBC_NAMESPACE -- GitLab From 5442e15a152614628e2e2bef250c91eacf75fc9c Mon Sep 17 00:00:00 2001 From: "Nick Desaulniers (paternity leave)" Date: Tue, 21 May 2024 15:49:42 -0700 Subject: [PATCH 046/452] [libc][__support] move CndVar to __support (#89329) We should be able to reuse this between the implementation of C11 cnd_t condition variables and POSIX pthread_cond_t condition variables. The current implementation is hyper linux specific, making use of Futex. That obviously wont work outside of linux, so split the OS specific functions off into their own source outside of the header. Modifies the return values of the to-be-shared impl to return 0 on success and -1 on error. This pattern was shamelessly stolen from Bionic's [__bionic_thrd_error](https://android.googlesource.com/platform/bionic/+/refs/heads/main/libc/include/bits/threads_inlines.h#41). Fixes: #88580 Link: #88583 --- libc/src/__support/threads/CMakeLists.txt | 9 ++ libc/src/__support/threads/CndVar.h | 52 ++++++ .../__support/threads/linux/CMakeLists.txt | 13 ++ libc/src/__support/threads/linux/CndVar.cpp | 103 ++++++++++++ libc/src/threads/linux/CMakeLists.txt | 11 +- libc/src/threads/linux/CndVar.h | 148 ------------------ libc/src/threads/linux/cnd_broadcast.cpp | 11 +- libc/src/threads/linux/cnd_destroy.cpp | 7 +- libc/src/threads/linux/cnd_init.cpp | 9 +- libc/src/threads/linux/cnd_signal.cpp | 10 +- libc/src/threads/linux/cnd_wait.cpp | 11 +- 11 files changed, 215 insertions(+), 169 deletions(-) create mode 100644 libc/src/__support/threads/CndVar.h create mode 100644 libc/src/__support/threads/linux/CndVar.cpp delete mode 100644 libc/src/threads/linux/CndVar.h diff --git a/libc/src/__support/threads/CMakeLists.txt b/libc/src/__support/threads/CMakeLists.txt index 34412be4dfed..9ea0b59befe7 100644 --- a/libc/src/__support/threads/CMakeLists.txt +++ b/libc/src/__support/threads/CMakeLists.txt @@ -71,3 +71,12 @@ if(TARGET libc.src.__support.threads.${LIBC_TARGET_OS}.callonce) .${LIBC_TARGET_OS}.callonce ) endif() + +if(TARGET libc.src.__support.threads.${LIBC_TARGET_OS}.CndVar) + add_object_library( + CndVar + ALIAS + DEPENDS + .${LIBC_TARGET_OS}.CndVar + ) +endif() diff --git a/libc/src/__support/threads/CndVar.h b/libc/src/__support/threads/CndVar.h new file mode 100644 index 000000000000..baa2a686c57d --- /dev/null +++ b/libc/src/__support/threads/CndVar.h @@ -0,0 +1,52 @@ +//===-- A platform independent abstraction layer for cond vars --*- C++ -*-===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LIBC___SUPPORT_SRC_THREADS_LINUX_CNDVAR_H +#define LLVM_LIBC___SUPPORT_SRC_THREADS_LINUX_CNDVAR_H + +#include "src/__support/threads/linux/futex_utils.h" // Futex +#include "src/__support/threads/mutex.h" // Mutex + +#include // uint32_t + +namespace LIBC_NAMESPACE { + +struct CndVar { + enum CndWaiterStatus : uint32_t { + WS_Waiting = 0xE, + WS_Signalled = 0x5, + }; + + struct CndWaiter { + Futex futex_word = WS_Waiting; + CndWaiter *next = nullptr; + }; + + CndWaiter *waitq_front; + CndWaiter *waitq_back; + Mutex qmtx; + + static int init(CndVar *cv) { + cv->waitq_front = cv->waitq_back = nullptr; + auto err = Mutex::init(&cv->qmtx, false, false, false); + return err == MutexError::NONE ? 0 : -1; + } + + static void destroy(CndVar *cv) { + cv->waitq_front = cv->waitq_back = nullptr; + } + + // Returns 0 on success, -1 on error. + int wait(Mutex *m); + void notify_one(); + void broadcast(); +}; + +} // namespace LIBC_NAMESPACE + +#endif // LLVM_LIBC_SRC___SUPPORT_THREADS_LINUX_CNDVAR_H diff --git a/libc/src/__support/threads/linux/CMakeLists.txt b/libc/src/__support/threads/linux/CMakeLists.txt index d3353f6b3ff8..39c4ad20201c 100644 --- a/libc/src/__support/threads/linux/CMakeLists.txt +++ b/libc/src/__support/threads/linux/CMakeLists.txt @@ -63,3 +63,16 @@ add_object_library( DEPENDS .futex_utils ) + +add_object_library( + CndVar + SRCS + CndVar.cpp + HDRS + ../CndVar.h + DEPENDS + libc.include.sys_syscall + libc.src.__support.OSUtil.osutil + libc.src.__support.threads.linux.futex_word_type + libc.src.__support.threads.mutex +) diff --git a/libc/src/__support/threads/linux/CndVar.cpp b/libc/src/__support/threads/linux/CndVar.cpp new file mode 100644 index 000000000000..daf56bca1ed2 --- /dev/null +++ b/libc/src/__support/threads/linux/CndVar.cpp @@ -0,0 +1,103 @@ +//===-- Utility condition variable class ------------------------*- C++ -*-===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +#include "src/__support/threads/CndVar.h" +#include "src/__support/OSUtil/syscall.h" // syscall_impl +#include "src/__support/threads/linux/futex_word.h" // FutexWordType +#include "src/__support/threads/mutex.h" // Mutex, MutexLock + +#include // For syscall numbers. + +namespace LIBC_NAMESPACE { + +int CndVar::wait(Mutex *m) { + // The goal is to perform "unlock |m| and wait" in an + // atomic operation. However, it is not possible to do it + // in the true sense so we do it in spirit. Before unlocking + // |m|, a new waiter object is added to the waiter queue with + // the waiter queue locked. Iff a signalling thread signals + // the waiter before the waiter actually starts waiting, the + // wait operation will not begin at all and the waiter immediately + // returns. + + CndWaiter waiter; + { + MutexLock ml(&qmtx); + CndWaiter *old_back = nullptr; + if (waitq_front == nullptr) { + waitq_front = waitq_back = &waiter; + } else { + old_back = waitq_back; + waitq_back->next = &waiter; + waitq_back = &waiter; + } + + if (m->unlock() != MutexError::NONE) { + // If we do not remove the queued up waiter before returning, + // then another thread can potentially signal a non-existing + // waiter. Note also that we do this with |qmtx| locked. This + // ensures that another thread will not signal the withdrawing + // waiter. + waitq_back = old_back; + if (waitq_back == nullptr) + waitq_front = nullptr; + else + waitq_back->next = nullptr; + + return -1; + } + } + + waiter.futex_word.wait(WS_Waiting, cpp::nullopt, true); + + // At this point, if locking |m| fails, we can simply return as the + // queued up waiter would have been removed from the queue. + auto err = m->lock(); + return err == MutexError::NONE ? 0 : -1; +} + +void CndVar::notify_one() { + // We don't use an RAII locker in this method as we want to unlock + // |qmtx| and signal the waiter using a single FUTEX_WAKE_OP signal. + qmtx.lock(); + if (waitq_front == nullptr) + qmtx.unlock(); + + CndWaiter *first = waitq_front; + waitq_front = waitq_front->next; + if (waitq_front == nullptr) + waitq_back = nullptr; + + qmtx.futex_word = FutexWordType(Mutex::LockState::Free); + + // this is a special WAKE_OP, so we use syscall directly + LIBC_NAMESPACE::syscall_impl( + FUTEX_SYSCALL_ID, &qmtx.futex_word.val, FUTEX_WAKE_OP, 1, 1, + &first->futex_word.val, + FUTEX_OP(FUTEX_OP_SET, WS_Signalled, FUTEX_OP_CMP_EQ, WS_Waiting)); +} + +void CndVar::broadcast() { + MutexLock ml(&qmtx); + uint32_t dummy_futex_word; + CndWaiter *waiter = waitq_front; + waitq_front = waitq_back = nullptr; + while (waiter != nullptr) { + // FUTEX_WAKE_OP is used instead of just FUTEX_WAKE as it allows us to + // atomically update the waiter status to WS_Signalled before waking + // up the waiter. A dummy location is used for the other futex of + // FUTEX_WAKE_OP. + LIBC_NAMESPACE::syscall_impl( + FUTEX_SYSCALL_ID, &dummy_futex_word, FUTEX_WAKE_OP, 1, 1, + &waiter->futex_word.val, + FUTEX_OP(FUTEX_OP_SET, WS_Signalled, FUTEX_OP_CMP_EQ, WS_Waiting)); + waiter = waiter->next; + } +} + +} // namespace LIBC_NAMESPACE diff --git a/libc/src/threads/linux/CMakeLists.txt b/libc/src/threads/linux/CMakeLists.txt index 68b7106c2052..a5a02e47aab3 100644 --- a/libc/src/threads/linux/CMakeLists.txt +++ b/libc/src/threads/linux/CMakeLists.txt @@ -1,7 +1,6 @@ add_header_library( threads_utils HDRS - CndVar.h Futex.h DEPENDS libc.include.sys_syscall @@ -20,8 +19,8 @@ add_entrypoint_object( HDRS ../cnd_init.h DEPENDS - .threads_utils libc.include.threads + libc.src.__support.threads.CndVar ) add_entrypoint_object( @@ -31,8 +30,8 @@ add_entrypoint_object( HDRS ../cnd_destroy.h DEPENDS - .threads_utils libc.include.threads + libc.src.__support.threads.CndVar ) add_entrypoint_object( @@ -42,9 +41,9 @@ add_entrypoint_object( HDRS ../cnd_wait.h DEPENDS - .threads_utils libc.include.threads libc.src.__support.threads.mutex + libc.src.__support.threads.CndVar ) add_entrypoint_object( @@ -54,8 +53,8 @@ add_entrypoint_object( HDRS ../cnd_signal.h DEPENDS - .threads_utils libc.include.threads + libc.src.__support.threads.CndVar ) add_entrypoint_object( @@ -65,6 +64,6 @@ add_entrypoint_object( HDRS ../cnd_broadcast.h DEPENDS - .threads_utils libc.include.threads + libc.src.__support.threads.CndVar ) diff --git a/libc/src/threads/linux/CndVar.h b/libc/src/threads/linux/CndVar.h deleted file mode 100644 index c08ffa393856..000000000000 --- a/libc/src/threads/linux/CndVar.h +++ /dev/null @@ -1,148 +0,0 @@ -//===-- Utility condition variable class ------------------------*- C++ -*-===// -// -// 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 -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_LIBC_SRC_THREADS_LINUX_CNDVAR_H -#define LLVM_LIBC_SRC_THREADS_LINUX_CNDVAR_H - -#include "src/__support/CPP/atomic.h" -#include "src/__support/CPP/mutex.h" // lock_guard -#include "src/__support/CPP/optional.h" -#include "src/__support/OSUtil/syscall.h" // For syscall functions. -#include "src/__support/threads/linux/futex_utils.h" -#include "src/__support/threads/mutex.h" - -#include // For futex operations. -#include -#include // For syscall numbers. -#include // For values like thrd_success etc. - -namespace LIBC_NAMESPACE { - -struct CndVar { - enum CndWaiterStatus : uint32_t { - WS_Waiting = 0xE, - WS_Signalled = 0x5, - }; - - struct CndWaiter { - Futex futex_word = WS_Waiting; - CndWaiter *next = nullptr; - }; - - CndWaiter *waitq_front; - CndWaiter *waitq_back; - Mutex qmtx; - - static int init(CndVar *cv) { - cv->waitq_front = cv->waitq_back = nullptr; - auto err = Mutex::init(&cv->qmtx, false, false, false); - return err == MutexError::NONE ? thrd_success : thrd_error; - } - - static void destroy(CndVar *cv) { - cv->waitq_front = cv->waitq_back = nullptr; - } - - int wait(Mutex *m) { - // The goal is to perform "unlock |m| and wait" in an - // atomic operation. However, it is not possible to do it - // in the true sense so we do it in spirit. Before unlocking - // |m|, a new waiter object is added to the waiter queue with - // the waiter queue locked. Iff a signalling thread signals - // the waiter before the waiter actually starts waiting, the - // wait operation will not begin at all and the waiter immediately - // returns. - - CndWaiter waiter; - { - cpp::lock_guard ml(qmtx); - CndWaiter *old_back = nullptr; - if (waitq_front == nullptr) { - waitq_front = waitq_back = &waiter; - } else { - old_back = waitq_back; - waitq_back->next = &waiter; - waitq_back = &waiter; - } - - if (m->unlock() != MutexError::NONE) { - // If we do not remove the queued up waiter before returning, - // then another thread can potentially signal a non-existing - // waiter. Note also that we do this with |qmtx| locked. This - // ensures that another thread will not signal the withdrawing - // waiter. - waitq_back = old_back; - if (waitq_back == nullptr) - waitq_front = nullptr; - else - waitq_back->next = nullptr; - - return thrd_error; - } - } - - waiter.futex_word.wait(WS_Waiting, cpp::nullopt, true); - - // At this point, if locking |m| fails, we can simply return as the - // queued up waiter would have been removed from the queue. - auto err = m->lock(); - return err == MutexError::NONE ? thrd_success : thrd_error; - } - - int notify_one() { - // We don't use an RAII locker in this method as we want to unlock - // |qmtx| and signal the waiter using a single FUTEX_WAKE_OP signal. - qmtx.lock(); - if (waitq_front == nullptr) { - qmtx.unlock(); - return thrd_success; - } - - CndWaiter *first = waitq_front; - waitq_front = waitq_front->next; - if (waitq_front == nullptr) - waitq_back = nullptr; - - qmtx.futex_word = FutexWordType(Mutex::LockState::Free); - - // this is a special WAKE_OP, so we use syscall directly - LIBC_NAMESPACE::syscall_impl( - FUTEX_SYSCALL_ID, &qmtx.futex_word.val, FUTEX_WAKE_OP, 1, 1, - &first->futex_word.val, - FUTEX_OP(FUTEX_OP_SET, WS_Signalled, FUTEX_OP_CMP_EQ, WS_Waiting)); - return thrd_success; - } - - int broadcast() { - cpp::lock_guard ml(qmtx); - uint32_t dummy_futex_word; - CndWaiter *waiter = waitq_front; - waitq_front = waitq_back = nullptr; - while (waiter != nullptr) { - // FUTEX_WAKE_OP is used instead of just FUTEX_WAKE as it allows us to - // atomically update the waiter status to WS_Signalled before waking - // up the waiter. A dummy location is used for the other futex of - // FUTEX_WAKE_OP. - LIBC_NAMESPACE::syscall_impl( - FUTEX_SYSCALL_ID, &dummy_futex_word, FUTEX_WAKE_OP, 1, 1, - &waiter->futex_word.val, - FUTEX_OP(FUTEX_OP_SET, WS_Signalled, FUTEX_OP_CMP_EQ, WS_Waiting)); - waiter = waiter->next; - } - return thrd_success; - } -}; - -static_assert(sizeof(CndVar) == sizeof(cnd_t), - "Mismatch in the size of the " - "internal representation of condition variable and the public " - "cnd_t type."); - -} // namespace LIBC_NAMESPACE - -#endif // LLVM_LIBC_SRC_THREADS_LINUX_CNDVAR_H diff --git a/libc/src/threads/linux/cnd_broadcast.cpp b/libc/src/threads/linux/cnd_broadcast.cpp index 180ac6d68ee8..a56aaa21ee12 100644 --- a/libc/src/threads/linux/cnd_broadcast.cpp +++ b/libc/src/threads/linux/cnd_broadcast.cpp @@ -6,16 +6,21 @@ // //===----------------------------------------------------------------------===// -#include "CndVar.h" - #include "src/threads/cnd_broadcast.h" #include "src/__support/common.h" +#include "src/__support/threads/CndVar.h" + +// TODO: https://github.com/llvm/llvm-project/issues/92968 +#include // cnd_t, thrd_error, thrd_success namespace LIBC_NAMESPACE { +static_assert(sizeof(CndVar) == sizeof(cnd_t)); + LLVM_LIBC_FUNCTION(int, cnd_broadcast, (cnd_t * cond)) { CndVar *cndvar = reinterpret_cast(cond); - return cndvar->broadcast(); + cndvar->broadcast(); + return thrd_success; } } // namespace LIBC_NAMESPACE diff --git a/libc/src/threads/linux/cnd_destroy.cpp b/libc/src/threads/linux/cnd_destroy.cpp index 08eb3a1057b1..2b03b18c48e4 100644 --- a/libc/src/threads/linux/cnd_destroy.cpp +++ b/libc/src/threads/linux/cnd_destroy.cpp @@ -6,13 +6,16 @@ // //===----------------------------------------------------------------------===// -#include "CndVar.h" - #include "src/threads/cnd_destroy.h" #include "src/__support/common.h" +#include "src/__support/threads/CndVar.h" + +#include // cnd_t namespace LIBC_NAMESPACE { +static_assert(sizeof(CndVar) == sizeof(cnd_t)); + LLVM_LIBC_FUNCTION(void, cnd_destroy, (cnd_t * cond)) { CndVar *cndvar = reinterpret_cast(cond); CndVar::destroy(cndvar); diff --git a/libc/src/threads/linux/cnd_init.cpp b/libc/src/threads/linux/cnd_init.cpp index 5e3f360b1d2b..d3d2c8a57d82 100644 --- a/libc/src/threads/linux/cnd_init.cpp +++ b/libc/src/threads/linux/cnd_init.cpp @@ -6,16 +6,19 @@ // //===----------------------------------------------------------------------===// -#include "CndVar.h" - #include "src/threads/cnd_init.h" #include "src/__support/common.h" +#include "src/__support/threads/CndVar.h" + +#include // cnd_t, thrd_error, thrd_success namespace LIBC_NAMESPACE { +static_assert(sizeof(CndVar) == sizeof(cnd_t)); + LLVM_LIBC_FUNCTION(int, cnd_init, (cnd_t * cond)) { CndVar *cndvar = reinterpret_cast(cond); - return CndVar::init(cndvar); + return CndVar::init(cndvar) ? thrd_error : thrd_success; } } // namespace LIBC_NAMESPACE diff --git a/libc/src/threads/linux/cnd_signal.cpp b/libc/src/threads/linux/cnd_signal.cpp index dba01abdefbc..f144013e0882 100644 --- a/libc/src/threads/linux/cnd_signal.cpp +++ b/libc/src/threads/linux/cnd_signal.cpp @@ -6,16 +6,20 @@ // //===----------------------------------------------------------------------===// -#include "CndVar.h" - #include "src/threads/cnd_signal.h" #include "src/__support/common.h" +#include "src/__support/threads/CndVar.h" + +#include // cnd_t, thrd_error, thrd_success namespace LIBC_NAMESPACE { +static_assert(sizeof(CndVar) == sizeof(cnd_t)); + LLVM_LIBC_FUNCTION(int, cnd_signal, (cnd_t * cond)) { CndVar *cndvar = reinterpret_cast(cond); - return cndvar->notify_one(); + cndvar->notify_one(); + return thrd_success; } } // namespace LIBC_NAMESPACE diff --git a/libc/src/threads/linux/cnd_wait.cpp b/libc/src/threads/linux/cnd_wait.cpp index db3d7f1436eb..97cade3f231d 100644 --- a/libc/src/threads/linux/cnd_wait.cpp +++ b/libc/src/threads/linux/cnd_wait.cpp @@ -6,18 +6,21 @@ // //===----------------------------------------------------------------------===// -#include "CndVar.h" - +#include "src/threads/cnd_wait.h" #include "src/__support/common.h" +#include "src/__support/threads/CndVar.h" #include "src/__support/threads/mutex.h" -#include "src/threads/cnd_wait.h" + +#include // cnd_t, mtx_t, thrd_error, thrd_success namespace LIBC_NAMESPACE { +static_assert(sizeof(CndVar) == sizeof(cnd_t)); + LLVM_LIBC_FUNCTION(int, cnd_wait, (cnd_t * cond, mtx_t *mtx)) { CndVar *cndvar = reinterpret_cast(cond); Mutex *mutex = reinterpret_cast(mtx); - return cndvar->wait(mutex); + return cndvar->wait(mutex) ? thrd_error : thrd_success; } } // namespace LIBC_NAMESPACE -- GitLab From 2e7365eabe4dd2a56b0b1b4053a95558c4f4bb97 Mon Sep 17 00:00:00 2001 From: Thomas Fransham Date: Tue, 21 May 2024 23:51:20 +0100 Subject: [PATCH 047/452] [lldb] Set ObjectFile's assignment operator to also be deleted like its copy constructor (#92942) This will also fix a warning when ObjectFile is dllexport'ed on Windows for my GSOC project for adding support Clang plugins on windows with @vgvassilev and @compnerd. --- llvm/include/llvm/Object/ObjectFile.h | 1 + 1 file changed, 1 insertion(+) diff --git a/llvm/include/llvm/Object/ObjectFile.h b/llvm/include/llvm/Object/ObjectFile.h index 8c868c7643ed..a50766ccaeb8 100644 --- a/llvm/include/llvm/Object/ObjectFile.h +++ b/llvm/include/llvm/Object/ObjectFile.h @@ -302,6 +302,7 @@ protected: public: ObjectFile() = delete; ObjectFile(const ObjectFile &other) = delete; + ObjectFile &opeartor = (const ObjectFile &other) = delete; uint64_t getCommonSymbolSize(DataRefImpl Symb) const { Expected SymbolFlagsOrErr = getSymbolFlags(Symb); -- GitLab From 42ba740afffa16f991be6aa36626bd872d41ebc0 Mon Sep 17 00:00:00 2001 From: Damien L-G Date: Tue, 21 May 2024 18:54:08 -0400 Subject: [PATCH 048/452] [libc++] Implement C++20 atomic_ref (#76647) Implement the std::atomic_ref class template by reusing atomic_base_impl. Based on the work from https://reviews.llvm.org/D72240 --- libcxx/docs/ReleaseNotes/19.rst | 1 + libcxx/docs/Status/Cxx20Papers.csv | 4 +- libcxx/include/CMakeLists.txt | 2 + libcxx/include/__atomic/atomic_ref.h | 360 ++++++++ libcxx/include/__atomic/atomic_sync.h | 1 + libcxx/include/__atomic/check_memory_order.h | 4 + libcxx/include/__atomic/cxx_atomic_impl.h | 27 +- libcxx/include/__atomic/to_gcc_order.h | 54 ++ libcxx/include/atomic | 1 + libcxx/include/libcxx.imp | 869 ++++++++++++++++++ libcxx/include/module.modulemap | 10 +- libcxx/modules/std/atomic.inc | 2 +- .../assert.compare_exchange_strong.pass.cpp | 58 ++ .../assert.compare_exchange_weak.pass.cpp | 58 ++ .../atomics/atomics.ref/assert.ctor.pass.cpp | 40 + .../atomics/atomics.ref/assert.load.pass.cpp | 55 ++ .../atomics/atomics.ref/assert.store.pass.cpp | 63 ++ .../atomics/atomics.ref/assert.wait.pass.cpp | 55 ++ .../std/atomics/atomics.ref/assign.pass.cpp | 50 + .../atomics.ref/bitwise_and_assign.pass.cpp | 60 ++ .../atomics.ref/bitwise_or_assign.pass.cpp | 56 ++ .../atomics.ref/bitwise_xor_assign.pass.cpp | 56 ++ .../compare_exchange_strong.pass.cpp | 221 +++++ .../compare_exchange_weak.pass.cpp | 226 +++++ .../std/atomics/atomics.ref/convert.pass.cpp | 45 + .../std/atomics/atomics.ref/ctor.pass.cpp | 37 + .../atomics/atomics.ref/deduction.pass.cpp | 33 + .../std/atomics/atomics.ref/exchange.pass.cpp | 45 + .../atomics/atomics.ref/fetch_add.pass.cpp | 113 +++ .../atomics/atomics.ref/fetch_and.pass.cpp | 69 ++ .../std/atomics/atomics.ref/fetch_or.pass.cpp | 68 ++ .../atomics/atomics.ref/fetch_sub.pass.cpp | 113 +++ .../atomics/atomics.ref/fetch_xor.pass.cpp | 68 ++ .../atomics.ref/increment_decrement.pass.cpp | 97 ++ .../atomics.ref/is_always_lock_free.pass.cpp | 71 ++ .../std/atomics/atomics.ref/load.pass.cpp | 62 ++ .../atomics/atomics.ref/member_types.pass.cpp | 132 +++ .../atomics/atomics.ref/notify_all.pass.cpp | 78 ++ .../atomics/atomics.ref/notify_one.pass.cpp | 46 + .../operator_minus_equals.pass.cpp | 79 ++ .../atomics.ref/operator_plus_equals.pass.cpp | 79 ++ .../atomics.ref/required_alignment.pass.cpp | 39 + .../requires-trivially-copyable.verify.cpp | 26 + .../std/atomics/atomics.ref/store.pass.cpp | 61 ++ .../std/atomics/atomics.ref/test_helper.h | 136 +++ .../std/atomics/atomics.ref/wait.pass.cpp | 88 ++ 46 files changed, 3888 insertions(+), 30 deletions(-) create mode 100644 libcxx/include/__atomic/atomic_ref.h create mode 100644 libcxx/include/__atomic/to_gcc_order.h create mode 100644 libcxx/include/libcxx.imp create mode 100644 libcxx/test/libcxx/atomics/atomics.ref/assert.compare_exchange_strong.pass.cpp create mode 100644 libcxx/test/libcxx/atomics/atomics.ref/assert.compare_exchange_weak.pass.cpp create mode 100644 libcxx/test/libcxx/atomics/atomics.ref/assert.ctor.pass.cpp create mode 100644 libcxx/test/libcxx/atomics/atomics.ref/assert.load.pass.cpp create mode 100644 libcxx/test/libcxx/atomics/atomics.ref/assert.store.pass.cpp create mode 100644 libcxx/test/libcxx/atomics/atomics.ref/assert.wait.pass.cpp create mode 100644 libcxx/test/std/atomics/atomics.ref/assign.pass.cpp create mode 100644 libcxx/test/std/atomics/atomics.ref/bitwise_and_assign.pass.cpp create mode 100644 libcxx/test/std/atomics/atomics.ref/bitwise_or_assign.pass.cpp create mode 100644 libcxx/test/std/atomics/atomics.ref/bitwise_xor_assign.pass.cpp create mode 100644 libcxx/test/std/atomics/atomics.ref/compare_exchange_strong.pass.cpp create mode 100644 libcxx/test/std/atomics/atomics.ref/compare_exchange_weak.pass.cpp create mode 100644 libcxx/test/std/atomics/atomics.ref/convert.pass.cpp create mode 100644 libcxx/test/std/atomics/atomics.ref/ctor.pass.cpp create mode 100644 libcxx/test/std/atomics/atomics.ref/deduction.pass.cpp create mode 100644 libcxx/test/std/atomics/atomics.ref/exchange.pass.cpp create mode 100644 libcxx/test/std/atomics/atomics.ref/fetch_add.pass.cpp create mode 100644 libcxx/test/std/atomics/atomics.ref/fetch_and.pass.cpp create mode 100644 libcxx/test/std/atomics/atomics.ref/fetch_or.pass.cpp create mode 100644 libcxx/test/std/atomics/atomics.ref/fetch_sub.pass.cpp create mode 100644 libcxx/test/std/atomics/atomics.ref/fetch_xor.pass.cpp create mode 100644 libcxx/test/std/atomics/atomics.ref/increment_decrement.pass.cpp create mode 100644 libcxx/test/std/atomics/atomics.ref/is_always_lock_free.pass.cpp create mode 100644 libcxx/test/std/atomics/atomics.ref/load.pass.cpp create mode 100644 libcxx/test/std/atomics/atomics.ref/member_types.pass.cpp create mode 100644 libcxx/test/std/atomics/atomics.ref/notify_all.pass.cpp create mode 100644 libcxx/test/std/atomics/atomics.ref/notify_one.pass.cpp create mode 100644 libcxx/test/std/atomics/atomics.ref/operator_minus_equals.pass.cpp create mode 100644 libcxx/test/std/atomics/atomics.ref/operator_plus_equals.pass.cpp create mode 100644 libcxx/test/std/atomics/atomics.ref/required_alignment.pass.cpp create mode 100644 libcxx/test/std/atomics/atomics.ref/requires-trivially-copyable.verify.cpp create mode 100644 libcxx/test/std/atomics/atomics.ref/store.pass.cpp create mode 100644 libcxx/test/std/atomics/atomics.ref/test_helper.h create mode 100644 libcxx/test/std/atomics/atomics.ref/wait.pass.cpp diff --git a/libcxx/docs/ReleaseNotes/19.rst b/libcxx/docs/ReleaseNotes/19.rst index 83fcd40bb80c..0bc343acd281 100644 --- a/libcxx/docs/ReleaseNotes/19.rst +++ b/libcxx/docs/ReleaseNotes/19.rst @@ -53,6 +53,7 @@ Implemented Papers - P2387R3 - Pipe support for user-defined range adaptors - P2713R1 - Escaping improvements in ``std::format`` - P2231R1 - Missing ``constexpr`` in ``std::optional`` and ``std::variant`` +- P0019R8 - ``std::atomic_ref`` Improvements and New Features ----------------------------- diff --git a/libcxx/docs/Status/Cxx20Papers.csv b/libcxx/docs/Status/Cxx20Papers.csv index 955aa5f614af..6598cd18358f 100644 --- a/libcxx/docs/Status/Cxx20Papers.csv +++ b/libcxx/docs/Status/Cxx20Papers.csv @@ -26,7 +26,7 @@ "`P0905R1 `__","CWG","Symmetry for spaceship","Jacksonville","|Complete|","7.0","|spaceship|" "`P0966R1 `__","LWG","``string::reserve``\ Should Not Shrink","Jacksonville","|Complete| [#note-P0966]_","12.0" "","","","","","","" -"`P0019R8 `__","LWG","Atomic Ref","Rapperswil","","" +"`P0019R8 `__","LWG","Atomic Ref","Rapperswil","|Complete|","19.0" "`P0458R2 `__","LWG","Checking for Existence of an Element in Associative Containers","Rapperswil","|Complete|","13.0" "`P0475R1 `__","LWG","LWG 2511: guaranteed copy elision for piecewise construction","Rapperswil","|Complete|","" "`P0476R2 `__","LWG","Bit-casting object representations","Rapperswil","|Complete|","14.0" @@ -125,7 +125,7 @@ "`P1612R1 `__","LWG","Relocate Endian's Specification","Cologne","|Complete|","10.0" "`P1614R2 `__","LWG","The Mothership has Landed","Cologne","|In Progress|","" "`P1638R1 `__","LWG","basic_istream_view::iterator should not be copyable","Cologne","|Complete|","16.0","|ranges|" -"`P1643R1 `__","LWG","Add wait/notify to atomic_ref","Cologne","","" +"`P1643R1 `__","LWG","Add wait/notify to atomic_ref","Cologne","|Complete|","19.0" "`P1644R0 `__","LWG","Add wait/notify to atomic","Cologne","","" "`P1650R0 `__","LWG","Output std::chrono::days with 'd' suffix","Cologne","|Complete|","16.0" "`P1651R0 `__","LWG","bind_front should not unwrap reference_wrapper","Cologne","|Complete|","13.0" diff --git a/libcxx/include/CMakeLists.txt b/libcxx/include/CMakeLists.txt index 01e9c247560c..954e0c04ec85 100644 --- a/libcxx/include/CMakeLists.txt +++ b/libcxx/include/CMakeLists.txt @@ -224,6 +224,7 @@ set(files __atomic/atomic_flag.h __atomic/atomic_init.h __atomic/atomic_lock_free.h + __atomic/atomic_ref.h __atomic/atomic_sync.h __atomic/check_memory_order.h __atomic/contention_t.h @@ -232,6 +233,7 @@ set(files __atomic/is_always_lock_free.h __atomic/kill_dependency.h __atomic/memory_order.h + __atomic/to_gcc_order.h __availability __bit/bit_cast.h __bit/bit_ceil.h diff --git a/libcxx/include/__atomic/atomic_ref.h b/libcxx/include/__atomic/atomic_ref.h new file mode 100644 index 000000000000..156f1961151c --- /dev/null +++ b/libcxx/include/__atomic/atomic_ref.h @@ -0,0 +1,360 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// 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 +// +// Kokkos v. 4.0 +// Copyright (2022) National Technology & Engineering +// Solutions of Sandia, LLC (NTESS). +// +// Under the terms of Contract DE-NA0003525 with NTESS, +// the U.S. Government retains certain rights in this software. +// +//===---------------------------------------------------------------------===// + +#ifndef _LIBCPP___ATOMIC_ATOMIC_REF_H +#define _LIBCPP___ATOMIC_ATOMIC_REF_H + +#include <__assert> +#include <__atomic/atomic_sync.h> +#include <__atomic/check_memory_order.h> +#include <__atomic/to_gcc_order.h> +#include <__concepts/arithmetic.h> +#include <__concepts/same_as.h> +#include <__config> +#include <__memory/addressof.h> +#include <__type_traits/has_unique_object_representation.h> +#include <__type_traits/is_trivially_copyable.h> +#include +#include +#include + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_PUSH_MACROS +#include <__undef_macros> + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if _LIBCPP_STD_VER >= 20 + +template +struct __atomic_ref_base { +protected: + _Tp* __ptr_; + + _LIBCPP_HIDE_FROM_ABI __atomic_ref_base(_Tp& __obj) : __ptr_(std::addressof(__obj)) {} + +private: + _LIBCPP_HIDE_FROM_ABI static _Tp* __clear_padding(_Tp& __val) noexcept { + _Tp* __ptr = std::addressof(__val); +# if __has_builtin(__builtin_clear_padding) + __builtin_clear_padding(__ptr); +# endif + return __ptr; + } + + _LIBCPP_HIDE_FROM_ABI static bool __compare_exchange( + _Tp* __ptr, _Tp* __expected, _Tp* __desired, bool __is_weak, int __success, int __failure) noexcept { + if constexpr ( +# if __has_builtin(__builtin_clear_padding) + has_unique_object_representations_v<_Tp> || floating_point<_Tp> +# else + true // NOLINT(readability-simplify-boolean-expr) +# endif + ) { + return __atomic_compare_exchange(__ptr, __expected, __desired, __is_weak, __success, __failure); + } else { // _Tp has padding bits and __builtin_clear_padding is available + __clear_padding(*__desired); + _Tp __copy = *__expected; + __clear_padding(__copy); + // The algorithm we use here is basically to perform `__atomic_compare_exchange` on the + // values until it has either succeeded, or failed because the value representation of the + // objects involved was different. This is why we loop around __atomic_compare_exchange: + // we basically loop until its failure is caused by the value representation of the objects + // being different, not only their object representation. + while (true) { + _Tp __prev = __copy; + if (__atomic_compare_exchange(__ptr, std::addressof(__copy), __desired, __is_weak, __success, __failure)) { + return true; + } + _Tp __curr = __copy; + if (std::memcmp(__clear_padding(__prev), __clear_padding(__curr), sizeof(_Tp)) != 0) { + // Value representation without padding bits do not compare equal -> + // write the current content of *ptr into *expected + std::memcpy(__expected, std::addressof(__copy), sizeof(_Tp)); + return false; + } + } + } + } + + friend struct __atomic_waitable_traits<__atomic_ref_base<_Tp>>; + +public: + using value_type = _Tp; + + static constexpr size_t required_alignment = alignof(_Tp); + + // The __atomic_always_lock_free builtin takes into account the alignment of the pointer if provided, + // so we create a fake pointer with a suitable alignment when querying it. Note that we are guaranteed + // that the pointer is going to be aligned properly at runtime because that is a (checked) precondition + // of atomic_ref's constructor. + static constexpr bool is_always_lock_free = + __atomic_always_lock_free(sizeof(_Tp), reinterpret_cast(-required_alignment)); + + _LIBCPP_HIDE_FROM_ABI bool is_lock_free() const noexcept { return __atomic_is_lock_free(sizeof(_Tp), __ptr_); } + + _LIBCPP_HIDE_FROM_ABI void store(_Tp __desired, memory_order __order = memory_order::seq_cst) const noexcept + _LIBCPP_CHECK_STORE_MEMORY_ORDER(__order) { + _LIBCPP_ASSERT_ARGUMENT_WITHIN_DOMAIN( + __order == memory_order::relaxed || __order == memory_order::release || __order == memory_order::seq_cst, + "atomic_ref: memory order argument to atomic store operation is invalid"); + __atomic_store(__ptr_, __clear_padding(__desired), std::__to_gcc_order(__order)); + } + + _LIBCPP_HIDE_FROM_ABI _Tp operator=(_Tp __desired) const noexcept { + store(__desired); + return __desired; + } + + _LIBCPP_HIDE_FROM_ABI _Tp load(memory_order __order = memory_order::seq_cst) const noexcept + _LIBCPP_CHECK_LOAD_MEMORY_ORDER(__order) { + _LIBCPP_ASSERT_ARGUMENT_WITHIN_DOMAIN( + __order == memory_order::relaxed || __order == memory_order::consume || __order == memory_order::acquire || + __order == memory_order::seq_cst, + "atomic_ref: memory order argument to atomic load operation is invalid"); + alignas(_Tp) byte __mem[sizeof(_Tp)]; + auto* __ret = reinterpret_cast<_Tp*>(__mem); + __atomic_load(__ptr_, __ret, std::__to_gcc_order(__order)); + return *__ret; + } + + _LIBCPP_HIDE_FROM_ABI operator _Tp() const noexcept { return load(); } + + _LIBCPP_HIDE_FROM_ABI _Tp exchange(_Tp __desired, memory_order __order = memory_order::seq_cst) const noexcept { + alignas(_Tp) byte __mem[sizeof(_Tp)]; + auto* __ret = reinterpret_cast<_Tp*>(__mem); + __atomic_exchange(__ptr_, __clear_padding(__desired), __ret, std::__to_gcc_order(__order)); + return *__ret; + } + + _LIBCPP_HIDE_FROM_ABI bool + compare_exchange_weak(_Tp& __expected, _Tp __desired, memory_order __success, memory_order __failure) const noexcept + _LIBCPP_CHECK_EXCHANGE_MEMORY_ORDER(__success, __failure) { + _LIBCPP_ASSERT_ARGUMENT_WITHIN_DOMAIN( + __failure == memory_order::relaxed || __failure == memory_order::consume || + __failure == memory_order::acquire || __failure == memory_order::seq_cst, + "atomic_ref: failure memory order argument to weak atomic compare-and-exchange operation is invalid"); + return __compare_exchange( + __ptr_, + std::addressof(__expected), + std::addressof(__desired), + true, + std::__to_gcc_order(__success), + std::__to_gcc_order(__failure)); + } + _LIBCPP_HIDE_FROM_ABI bool + compare_exchange_strong(_Tp& __expected, _Tp __desired, memory_order __success, memory_order __failure) const noexcept + _LIBCPP_CHECK_EXCHANGE_MEMORY_ORDER(__success, __failure) { + _LIBCPP_ASSERT_ARGUMENT_WITHIN_DOMAIN( + __failure == memory_order::relaxed || __failure == memory_order::consume || + __failure == memory_order::acquire || __failure == memory_order::seq_cst, + "atomic_ref: failure memory order argument to strong atomic compare-and-exchange operation is invalid"); + return __compare_exchange( + __ptr_, + std::addressof(__expected), + std::addressof(__desired), + false, + std::__to_gcc_order(__success), + std::__to_gcc_order(__failure)); + } + + _LIBCPP_HIDE_FROM_ABI bool + compare_exchange_weak(_Tp& __expected, _Tp __desired, memory_order __order = memory_order::seq_cst) const noexcept { + return __compare_exchange( + __ptr_, + std::addressof(__expected), + std::addressof(__desired), + true, + std::__to_gcc_order(__order), + std::__to_gcc_failure_order(__order)); + } + _LIBCPP_HIDE_FROM_ABI bool + compare_exchange_strong(_Tp& __expected, _Tp __desired, memory_order __order = memory_order::seq_cst) const noexcept { + return __compare_exchange( + __ptr_, + std::addressof(__expected), + std::addressof(__desired), + false, + std::__to_gcc_order(__order), + std::__to_gcc_failure_order(__order)); + } + + _LIBCPP_HIDE_FROM_ABI void wait(_Tp __old, memory_order __order = memory_order::seq_cst) const noexcept + _LIBCPP_CHECK_WAIT_MEMORY_ORDER(__order) { + _LIBCPP_ASSERT_ARGUMENT_WITHIN_DOMAIN( + __order == memory_order::relaxed || __order == memory_order::consume || __order == memory_order::acquire || + __order == memory_order::seq_cst, + "atomic_ref: memory order argument to atomic wait operation is invalid"); + std::__atomic_wait(*this, __old, __order); + } + _LIBCPP_HIDE_FROM_ABI void notify_one() const noexcept { std::__atomic_notify_one(*this); } + _LIBCPP_HIDE_FROM_ABI void notify_all() const noexcept { std::__atomic_notify_all(*this); } +}; + +template +struct __atomic_waitable_traits<__atomic_ref_base<_Tp>> { + static _LIBCPP_HIDE_FROM_ABI _Tp __atomic_load(const __atomic_ref_base<_Tp>& __a, memory_order __order) { + return __a.load(__order); + } + static _LIBCPP_HIDE_FROM_ABI const _Tp* __atomic_contention_address(const __atomic_ref_base<_Tp>& __a) { + return __a.__ptr_; + } +}; + +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>; + + _LIBCPP_HIDE_FROM_ABI explicit atomic_ref(_Tp& __obj) : __base(__obj) { + _LIBCPP_ASSERT_ARGUMENT_WITHIN_DOMAIN( + reinterpret_cast(std::addressof(__obj)) % __base::required_alignment == 0, + "atomic_ref ctor: referenced object must be aligned to required_alignment"); + } + + _LIBCPP_HIDE_FROM_ABI atomic_ref(const atomic_ref&) noexcept = default; + + _LIBCPP_HIDE_FROM_ABI _Tp operator=(_Tp __desired) const noexcept { return __base::operator=(__desired); } + + atomic_ref& operator=(const atomic_ref&) = delete; +}; + +template + requires(std::integral<_Tp> && !std::same_as) +struct atomic_ref<_Tp> : public __atomic_ref_base<_Tp> { + using __base = __atomic_ref_base<_Tp>; + + using difference_type = __base::value_type; + + _LIBCPP_HIDE_FROM_ABI explicit atomic_ref(_Tp& __obj) : __base(__obj) { + _LIBCPP_ASSERT_ARGUMENT_WITHIN_DOMAIN( + reinterpret_cast(std::addressof(__obj)) % __base::required_alignment == 0, + "atomic_ref ctor: referenced object must be aligned to required_alignment"); + } + + _LIBCPP_HIDE_FROM_ABI atomic_ref(const atomic_ref&) noexcept = default; + + _LIBCPP_HIDE_FROM_ABI _Tp operator=(_Tp __desired) const noexcept { return __base::operator=(__desired); } + + atomic_ref& operator=(const atomic_ref&) = delete; + + _LIBCPP_HIDE_FROM_ABI _Tp fetch_add(_Tp __arg, memory_order __order = memory_order_seq_cst) const noexcept { + return __atomic_fetch_add(this->__ptr_, __arg, std::__to_gcc_order(__order)); + } + _LIBCPP_HIDE_FROM_ABI _Tp fetch_sub(_Tp __arg, memory_order __order = memory_order_seq_cst) const noexcept { + return __atomic_fetch_sub(this->__ptr_, __arg, std::__to_gcc_order(__order)); + } + _LIBCPP_HIDE_FROM_ABI _Tp fetch_and(_Tp __arg, memory_order __order = memory_order_seq_cst) const noexcept { + return __atomic_fetch_and(this->__ptr_, __arg, std::__to_gcc_order(__order)); + } + _LIBCPP_HIDE_FROM_ABI _Tp fetch_or(_Tp __arg, memory_order __order = memory_order_seq_cst) const noexcept { + return __atomic_fetch_or(this->__ptr_, __arg, std::__to_gcc_order(__order)); + } + _LIBCPP_HIDE_FROM_ABI _Tp fetch_xor(_Tp __arg, memory_order __order = memory_order_seq_cst) const noexcept { + return __atomic_fetch_xor(this->__ptr_, __arg, std::__to_gcc_order(__order)); + } + + _LIBCPP_HIDE_FROM_ABI _Tp operator++(int) const noexcept { return fetch_add(_Tp(1)); } + _LIBCPP_HIDE_FROM_ABI _Tp operator--(int) const noexcept { return fetch_sub(_Tp(1)); } + _LIBCPP_HIDE_FROM_ABI _Tp operator++() const noexcept { return fetch_add(_Tp(1)) + _Tp(1); } + _LIBCPP_HIDE_FROM_ABI _Tp operator--() const noexcept { return fetch_sub(_Tp(1)) - _Tp(1); } + _LIBCPP_HIDE_FROM_ABI _Tp operator+=(_Tp __arg) const noexcept { return fetch_add(__arg) + __arg; } + _LIBCPP_HIDE_FROM_ABI _Tp operator-=(_Tp __arg) const noexcept { return fetch_sub(__arg) - __arg; } + _LIBCPP_HIDE_FROM_ABI _Tp operator&=(_Tp __arg) const noexcept { return fetch_and(__arg) & __arg; } + _LIBCPP_HIDE_FROM_ABI _Tp operator|=(_Tp __arg) const noexcept { return fetch_or(__arg) | __arg; } + _LIBCPP_HIDE_FROM_ABI _Tp operator^=(_Tp __arg) const noexcept { return fetch_xor(__arg) ^ __arg; } +}; + +template + requires std::floating_point<_Tp> +struct atomic_ref<_Tp> : public __atomic_ref_base<_Tp> { + using __base = __atomic_ref_base<_Tp>; + + using difference_type = __base::value_type; + + _LIBCPP_HIDE_FROM_ABI explicit atomic_ref(_Tp& __obj) : __base(__obj) { + _LIBCPP_ASSERT_ARGUMENT_WITHIN_DOMAIN( + reinterpret_cast(std::addressof(__obj)) % __base::required_alignment == 0, + "atomic_ref ctor: referenced object must be aligned to required_alignment"); + } + + _LIBCPP_HIDE_FROM_ABI atomic_ref(const atomic_ref&) noexcept = default; + + _LIBCPP_HIDE_FROM_ABI _Tp operator=(_Tp __desired) const noexcept { return __base::operator=(__desired); } + + atomic_ref& operator=(const atomic_ref&) = delete; + + _LIBCPP_HIDE_FROM_ABI _Tp fetch_add(_Tp __arg, memory_order __order = memory_order_seq_cst) const noexcept { + _Tp __old = this->load(memory_order_relaxed); + _Tp __new = __old + __arg; + while (!this->compare_exchange_weak(__old, __new, __order, memory_order_relaxed)) { + __new = __old + __arg; + } + return __old; + } + _LIBCPP_HIDE_FROM_ABI _Tp fetch_sub(_Tp __arg, memory_order __order = memory_order_seq_cst) const noexcept { + _Tp __old = this->load(memory_order_relaxed); + _Tp __new = __old - __arg; + while (!this->compare_exchange_weak(__old, __new, __order, memory_order_relaxed)) { + __new = __old - __arg; + } + return __old; + } + + _LIBCPP_HIDE_FROM_ABI _Tp operator+=(_Tp __arg) const noexcept { return fetch_add(__arg) + __arg; } + _LIBCPP_HIDE_FROM_ABI _Tp operator-=(_Tp __arg) const noexcept { return fetch_sub(__arg) - __arg; } +}; + +template +struct atomic_ref<_Tp*> : public __atomic_ref_base<_Tp*> { + using __base = __atomic_ref_base<_Tp*>; + + using difference_type = ptrdiff_t; + + _LIBCPP_HIDE_FROM_ABI explicit atomic_ref(_Tp*& __ptr) : __base(__ptr) {} + + _LIBCPP_HIDE_FROM_ABI _Tp* operator=(_Tp* __desired) const noexcept { return __base::operator=(__desired); } + + atomic_ref& operator=(const atomic_ref&) = delete; + + _LIBCPP_HIDE_FROM_ABI _Tp* fetch_add(ptrdiff_t __arg, memory_order __order = memory_order_seq_cst) const noexcept { + return __atomic_fetch_add(this->__ptr_, __arg * sizeof(_Tp), std::__to_gcc_order(__order)); + } + _LIBCPP_HIDE_FROM_ABI _Tp* fetch_sub(ptrdiff_t __arg, memory_order __order = memory_order_seq_cst) const noexcept { + return __atomic_fetch_sub(this->__ptr_, __arg * sizeof(_Tp), std::__to_gcc_order(__order)); + } + + _LIBCPP_HIDE_FROM_ABI _Tp* operator++(int) const noexcept { return fetch_add(1); } + _LIBCPP_HIDE_FROM_ABI _Tp* operator--(int) const noexcept { return fetch_sub(1); } + _LIBCPP_HIDE_FROM_ABI _Tp* operator++() const noexcept { return fetch_add(1) + 1; } + _LIBCPP_HIDE_FROM_ABI _Tp* operator--() const noexcept { return fetch_sub(1) - 1; } + _LIBCPP_HIDE_FROM_ABI _Tp* operator+=(ptrdiff_t __arg) const noexcept { return fetch_add(__arg) + __arg; } + _LIBCPP_HIDE_FROM_ABI _Tp* operator-=(ptrdiff_t __arg) const noexcept { return fetch_sub(__arg) - __arg; } +}; + +_LIBCPP_CTAD_SUPPORTED_FOR_TYPE(atomic_ref); + +#endif // _LIBCPP_STD_VER >= 20 + +_LIBCPP_END_NAMESPACE_STD + +_LIBCPP_POP_MACROS + +#endif // _LIBCPP__ATOMIC_ATOMIC_REF_H diff --git a/libcxx/include/__atomic/atomic_sync.h b/libcxx/include/__atomic/atomic_sync.h index e583dca38c4c..175700be54c0 100644 --- a/libcxx/include/__atomic/atomic_sync.h +++ b/libcxx/include/__atomic/atomic_sync.h @@ -12,6 +12,7 @@ #include <__atomic/contention_t.h> #include <__atomic/cxx_atomic_impl.h> #include <__atomic/memory_order.h> +#include <__atomic/to_gcc_order.h> #include <__availability> #include <__chrono/duration.h> #include <__config> diff --git a/libcxx/include/__atomic/check_memory_order.h b/libcxx/include/__atomic/check_memory_order.h index 3012aec0521b..536f764a6190 100644 --- a/libcxx/include/__atomic/check_memory_order.h +++ b/libcxx/include/__atomic/check_memory_order.h @@ -27,4 +27,8 @@ _LIBCPP_DIAGNOSE_WARNING(__f == memory_order_release || __f == memory_order_acq_rel, \ "memory order argument to atomic operation is invalid") +#define _LIBCPP_CHECK_WAIT_MEMORY_ORDER(__m) \ + _LIBCPP_DIAGNOSE_WARNING(__m == memory_order_release || __m == memory_order_acq_rel, \ + "memory order argument to atomic operation is invalid") + #endif // _LIBCPP___ATOMIC_CHECK_MEMORY_ORDER_H diff --git a/libcxx/include/__atomic/cxx_atomic_impl.h b/libcxx/include/__atomic/cxx_atomic_impl.h index b900cc135f78..18e88aa97bec 100644 --- a/libcxx/include/__atomic/cxx_atomic_impl.h +++ b/libcxx/include/__atomic/cxx_atomic_impl.h @@ -10,6 +10,7 @@ #define _LIBCPP___ATOMIC_CXX_ATOMIC_IMPL_H #include <__atomic/memory_order.h> +#include <__atomic/to_gcc_order.h> #include <__config> #include <__memory/addressof.h> #include <__type_traits/is_assignable.h> @@ -54,32 +55,6 @@ struct __cxx_atomic_base_impl { _Tp __a_value; }; -_LIBCPP_HIDE_FROM_ABI inline _LIBCPP_CONSTEXPR int __to_gcc_order(memory_order __order) { - // Avoid switch statement to make this a constexpr. - return __order == memory_order_relaxed - ? __ATOMIC_RELAXED - : (__order == memory_order_acquire - ? __ATOMIC_ACQUIRE - : (__order == memory_order_release - ? __ATOMIC_RELEASE - : (__order == memory_order_seq_cst - ? __ATOMIC_SEQ_CST - : (__order == memory_order_acq_rel ? __ATOMIC_ACQ_REL : __ATOMIC_CONSUME)))); -} - -_LIBCPP_HIDE_FROM_ABI inline _LIBCPP_CONSTEXPR int __to_gcc_failure_order(memory_order __order) { - // Avoid switch statement to make this a constexpr. - return __order == memory_order_relaxed - ? __ATOMIC_RELAXED - : (__order == memory_order_acquire - ? __ATOMIC_ACQUIRE - : (__order == memory_order_release - ? __ATOMIC_RELAXED - : (__order == memory_order_seq_cst - ? __ATOMIC_SEQ_CST - : (__order == memory_order_acq_rel ? __ATOMIC_ACQUIRE : __ATOMIC_CONSUME)))); -} - template _LIBCPP_HIDE_FROM_ABI void __cxx_atomic_init(volatile __cxx_atomic_base_impl<_Tp>* __a, _Tp __val) { __cxx_atomic_assign_volatile(__a->__a_value, __val); diff --git a/libcxx/include/__atomic/to_gcc_order.h b/libcxx/include/__atomic/to_gcc_order.h new file mode 100644 index 000000000000..d04c111addd3 --- /dev/null +++ b/libcxx/include/__atomic/to_gcc_order.h @@ -0,0 +1,54 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ATOMIC_TO_GCC_ORDER_H +#define _LIBCPP___ATOMIC_TO_GCC_ORDER_H + +#include <__atomic/memory_order.h> +#include <__config> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if defined(__ATOMIC_RELAXED) && defined(__ATOMIC_CONSUME) && defined(__ATOMIC_ACQUIRE) && \ + defined(__ATOMIC_RELEASE) && defined(__ATOMIC_ACQ_REL) && defined(__ATOMIC_SEQ_CST) + +_LIBCPP_HIDE_FROM_ABI inline _LIBCPP_CONSTEXPR int __to_gcc_order(memory_order __order) { + // Avoid switch statement to make this a constexpr. + return __order == memory_order_relaxed + ? __ATOMIC_RELAXED + : (__order == memory_order_acquire + ? __ATOMIC_ACQUIRE + : (__order == memory_order_release + ? __ATOMIC_RELEASE + : (__order == memory_order_seq_cst + ? __ATOMIC_SEQ_CST + : (__order == memory_order_acq_rel ? __ATOMIC_ACQ_REL : __ATOMIC_CONSUME)))); +} + +_LIBCPP_HIDE_FROM_ABI inline _LIBCPP_CONSTEXPR int __to_gcc_failure_order(memory_order __order) { + // Avoid switch statement to make this a constexpr. + return __order == memory_order_relaxed + ? __ATOMIC_RELAXED + : (__order == memory_order_acquire + ? __ATOMIC_ACQUIRE + : (__order == memory_order_release + ? __ATOMIC_RELAXED + : (__order == memory_order_seq_cst + ? __ATOMIC_SEQ_CST + : (__order == memory_order_acq_rel ? __ATOMIC_ACQUIRE : __ATOMIC_CONSUME)))); +} + +#endif + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___ATOMIC_TO_GCC_ORDER_H diff --git a/libcxx/include/atomic b/libcxx/include/atomic index cb142b09bff3..80a0f9ee373e 100644 --- a/libcxx/include/atomic +++ b/libcxx/include/atomic @@ -599,6 +599,7 @@ template #include <__atomic/atomic_flag.h> #include <__atomic/atomic_init.h> #include <__atomic/atomic_lock_free.h> +#include <__atomic/atomic_ref.h> #include <__atomic/atomic_sync.h> #include <__atomic/check_memory_order.h> #include <__atomic/contention_t.h> diff --git a/libcxx/include/libcxx.imp b/libcxx/include/libcxx.imp new file mode 100644 index 000000000000..f6aa1ea6b62b --- /dev/null +++ b/libcxx/include/libcxx.imp @@ -0,0 +1,869 @@ +[ + { include: [ "<__algorithm/adjacent_find.h>", "private", "", "public" ] }, + { include: [ "<__algorithm/all_of.h>", "private", "", "public" ] }, + { include: [ "<__algorithm/any_of.h>", "private", "", "public" ] }, + { include: [ "<__algorithm/binary_search.h>", "private", "", "public" ] }, + { include: [ "<__algorithm/clamp.h>", "private", "", "public" ] }, + { include: [ "<__algorithm/comp.h>", "private", "", "public" ] }, + { include: [ "<__algorithm/comp_ref_type.h>", "private", "", "public" ] }, + { include: [ "<__algorithm/copy.h>", "private", "", "public" ] }, + { include: [ "<__algorithm/copy_backward.h>", "private", "", "public" ] }, + { include: [ "<__algorithm/copy_if.h>", "private", "", "public" ] }, + { include: [ "<__algorithm/copy_move_common.h>", "private", "", "public" ] }, + { include: [ "<__algorithm/copy_n.h>", "private", "", "public" ] }, + { include: [ "<__algorithm/count.h>", "private", "", "public" ] }, + { include: [ "<__algorithm/count_if.h>", "private", "", "public" ] }, + { include: [ "<__algorithm/equal.h>", "private", "", "public" ] }, + { include: [ "<__algorithm/equal_range.h>", "private", "", "public" ] }, + { include: [ "<__algorithm/fill.h>", "private", "", "public" ] }, + { include: [ "<__algorithm/fill_n.h>", "private", "", "public" ] }, + { include: [ "<__algorithm/find.h>", "private", "", "public" ] }, + { include: [ "<__algorithm/find_end.h>", "private", "", "public" ] }, + { include: [ "<__algorithm/find_first_of.h>", "private", "", "public" ] }, + { include: [ "<__algorithm/find_if.h>", "private", "", "public" ] }, + { include: [ "<__algorithm/find_if_not.h>", "private", "", "public" ] }, + { include: [ "<__algorithm/find_segment_if.h>", "private", "", "public" ] }, + { include: [ "<__algorithm/fold.h>", "private", "", "public" ] }, + { include: [ "<__algorithm/for_each.h>", "private", "", "public" ] }, + { include: [ "<__algorithm/for_each_n.h>", "private", "", "public" ] }, + { include: [ "<__algorithm/for_each_segment.h>", "private", "", "public" ] }, + { include: [ "<__algorithm/generate.h>", "private", "", "public" ] }, + { include: [ "<__algorithm/generate_n.h>", "private", "", "public" ] }, + { include: [ "<__algorithm/half_positive.h>", "private", "", "public" ] }, + { include: [ "<__algorithm/in_found_result.h>", "private", "", "public" ] }, + { include: [ "<__algorithm/in_fun_result.h>", "private", "", "public" ] }, + { include: [ "<__algorithm/in_in_out_result.h>", "private", "", "public" ] }, + { include: [ "<__algorithm/in_in_result.h>", "private", "", "public" ] }, + { include: [ "<__algorithm/in_out_out_result.h>", "private", "", "public" ] }, + { include: [ "<__algorithm/in_out_result.h>", "private", "", "public" ] }, + { include: [ "<__algorithm/includes.h>", "private", "", "public" ] }, + { include: [ "<__algorithm/inplace_merge.h>", "private", "", "public" ] }, + { include: [ "<__algorithm/is_heap.h>", "private", "", "public" ] }, + { include: [ "<__algorithm/is_heap_until.h>", "private", "", "public" ] }, + { include: [ "<__algorithm/is_partitioned.h>", "private", "", "public" ] }, + { include: [ "<__algorithm/is_permutation.h>", "private", "", "public" ] }, + { include: [ "<__algorithm/is_sorted.h>", "private", "", "public" ] }, + { include: [ "<__algorithm/is_sorted_until.h>", "private", "", "public" ] }, + { include: [ "<__algorithm/iter_swap.h>", "private", "", "public" ] }, + { include: [ "<__algorithm/iterator_operations.h>", "private", "", "public" ] }, + { include: [ "<__algorithm/lexicographical_compare.h>", "private", "", "public" ] }, + { include: [ "<__algorithm/lexicographical_compare_three_way.h>", "private", "", "public" ] }, + { include: [ "<__algorithm/lower_bound.h>", "private", "", "public" ] }, + { include: [ "<__algorithm/make_heap.h>", "private", "", "public" ] }, + { include: [ "<__algorithm/make_projected.h>", "private", "", "public" ] }, + { include: [ "<__algorithm/max.h>", "private", "", "public" ] }, + { include: [ "<__algorithm/max_element.h>", "private", "", "public" ] }, + { include: [ "<__algorithm/merge.h>", "private", "", "public" ] }, + { include: [ "<__algorithm/min.h>", "private", "", "public" ] }, + { include: [ "<__algorithm/min_element.h>", "private", "", "public" ] }, + { include: [ "<__algorithm/min_max_result.h>", "private", "", "public" ] }, + { include: [ "<__algorithm/minmax.h>", "private", "", "public" ] }, + { include: [ "<__algorithm/minmax_element.h>", "private", "", "public" ] }, + { include: [ "<__algorithm/mismatch.h>", "private", "", "public" ] }, + { include: [ "<__algorithm/move.h>", "private", "", "public" ] }, + { include: [ "<__algorithm/move_backward.h>", "private", "", "public" ] }, + { include: [ "<__algorithm/next_permutation.h>", "private", "", "public" ] }, + { include: [ "<__algorithm/none_of.h>", "private", "", "public" ] }, + { include: [ "<__algorithm/nth_element.h>", "private", "", "public" ] }, + { include: [ "<__algorithm/partial_sort.h>", "private", "", "public" ] }, + { include: [ "<__algorithm/partial_sort_copy.h>", "private", "", "public" ] }, + { include: [ "<__algorithm/partition.h>", "private", "", "public" ] }, + { include: [ "<__algorithm/partition_copy.h>", "private", "", "public" ] }, + { include: [ "<__algorithm/partition_point.h>", "private", "", "public" ] }, + { include: [ "<__algorithm/pop_heap.h>", "private", "", "public" ] }, + { include: [ "<__algorithm/prev_permutation.h>", "private", "", "public" ] }, + { include: [ "<__algorithm/pstl_any_all_none_of.h>", "private", "", "public" ] }, + { include: [ "<__algorithm/pstl_backend.h>", "private", "", "public" ] }, + { include: [ "<__algorithm/pstl_backends/cpu_backend.h>", "private", "", "public" ] }, + { include: [ "<__algorithm/pstl_backends/cpu_backends/any_of.h>", "private", "", "public" ] }, + { include: [ "<__algorithm/pstl_backends/cpu_backends/backend.h>", "private", "", "public" ] }, + { include: [ "<__algorithm/pstl_backends/cpu_backends/fill.h>", "private", "", "public" ] }, + { include: [ "<__algorithm/pstl_backends/cpu_backends/find_if.h>", "private", "", "public" ] }, + { include: [ "<__algorithm/pstl_backends/cpu_backends/for_each.h>", "private", "", "public" ] }, + { include: [ "<__algorithm/pstl_backends/cpu_backends/libdispatch.h>", "private", "", "public" ] }, + { include: [ "<__algorithm/pstl_backends/cpu_backends/merge.h>", "private", "", "public" ] }, + { include: [ "<__algorithm/pstl_backends/cpu_backends/serial.h>", "private", "", "public" ] }, + { include: [ "<__algorithm/pstl_backends/cpu_backends/stable_sort.h>", "private", "", "public" ] }, + { include: [ "<__algorithm/pstl_backends/cpu_backends/thread.h>", "private", "", "public" ] }, + { include: [ "<__algorithm/pstl_backends/cpu_backends/transform.h>", "private", "", "public" ] }, + { include: [ "<__algorithm/pstl_backends/cpu_backends/transform_reduce.h>", "private", "", "public" ] }, + { include: [ "<__algorithm/pstl_copy.h>", "private", "", "public" ] }, + { include: [ "<__algorithm/pstl_count.h>", "private", "", "public" ] }, + { include: [ "<__algorithm/pstl_equal.h>", "private", "", "public" ] }, + { include: [ "<__algorithm/pstl_fill.h>", "private", "", "public" ] }, + { include: [ "<__algorithm/pstl_find.h>", "private", "", "public" ] }, + { include: [ "<__algorithm/pstl_for_each.h>", "private", "", "public" ] }, + { include: [ "<__algorithm/pstl_frontend_dispatch.h>", "private", "", "public" ] }, + { include: [ "<__algorithm/pstl_generate.h>", "private", "", "public" ] }, + { include: [ "<__algorithm/pstl_is_partitioned.h>", "private", "", "public" ] }, + { include: [ "<__algorithm/pstl_merge.h>", "private", "", "public" ] }, + { include: [ "<__algorithm/pstl_move.h>", "private", "", "public" ] }, + { include: [ "<__algorithm/pstl_replace.h>", "private", "", "public" ] }, + { include: [ "<__algorithm/pstl_rotate_copy.h>", "private", "", "public" ] }, + { include: [ "<__algorithm/pstl_sort.h>", "private", "", "public" ] }, + { include: [ "<__algorithm/pstl_stable_sort.h>", "private", "", "public" ] }, + { include: [ "<__algorithm/pstl_transform.h>", "private", "", "public" ] }, + { include: [ "<__algorithm/push_heap.h>", "private", "", "public" ] }, + { include: [ "<__algorithm/ranges_adjacent_find.h>", "private", "", "public" ] }, + { include: [ "<__algorithm/ranges_all_of.h>", "private", "", "public" ] }, + { include: [ "<__algorithm/ranges_any_of.h>", "private", "", "public" ] }, + { include: [ "<__algorithm/ranges_binary_search.h>", "private", "", "public" ] }, + { include: [ "<__algorithm/ranges_clamp.h>", "private", "", "public" ] }, + { include: [ "<__algorithm/ranges_contains.h>", "private", "", "public" ] }, + { include: [ "<__algorithm/ranges_contains_subrange.h>", "private", "", "public" ] }, + { include: [ "<__algorithm/ranges_copy.h>", "private", "", "public" ] }, + { include: [ "<__algorithm/ranges_copy_backward.h>", "private", "", "public" ] }, + { include: [ "<__algorithm/ranges_copy_if.h>", "private", "", "public" ] }, + { include: [ "<__algorithm/ranges_copy_n.h>", "private", "", "public" ] }, + { include: [ "<__algorithm/ranges_count.h>", "private", "", "public" ] }, + { include: [ "<__algorithm/ranges_count_if.h>", "private", "", "public" ] }, + { include: [ "<__algorithm/ranges_ends_with.h>", "private", "", "public" ] }, + { include: [ "<__algorithm/ranges_equal.h>", "private", "", "public" ] }, + { include: [ "<__algorithm/ranges_equal_range.h>", "private", "", "public" ] }, + { include: [ "<__algorithm/ranges_fill.h>", "private", "", "public" ] }, + { include: [ "<__algorithm/ranges_fill_n.h>", "private", "", "public" ] }, + { include: [ "<__algorithm/ranges_find.h>", "private", "", "public" ] }, + { include: [ "<__algorithm/ranges_find_end.h>", "private", "", "public" ] }, + { include: [ "<__algorithm/ranges_find_first_of.h>", "private", "", "public" ] }, + { include: [ "<__algorithm/ranges_find_if.h>", "private", "", "public" ] }, + { include: [ "<__algorithm/ranges_find_if_not.h>", "private", "", "public" ] }, + { include: [ "<__algorithm/ranges_for_each.h>", "private", "", "public" ] }, + { include: [ "<__algorithm/ranges_for_each_n.h>", "private", "", "public" ] }, + { include: [ "<__algorithm/ranges_generate.h>", "private", "", "public" ] }, + { include: [ "<__algorithm/ranges_generate_n.h>", "private", "", "public" ] }, + { include: [ "<__algorithm/ranges_includes.h>", "private", "", "public" ] }, + { include: [ "<__algorithm/ranges_inplace_merge.h>", "private", "", "public" ] }, + { include: [ "<__algorithm/ranges_is_heap.h>", "private", "", "public" ] }, + { include: [ "<__algorithm/ranges_is_heap_until.h>", "private", "", "public" ] }, + { include: [ "<__algorithm/ranges_is_partitioned.h>", "private", "", "public" ] }, + { include: [ "<__algorithm/ranges_is_permutation.h>", "private", "", "public" ] }, + { include: [ "<__algorithm/ranges_is_sorted.h>", "private", "", "public" ] }, + { include: [ "<__algorithm/ranges_is_sorted_until.h>", "private", "", "public" ] }, + { include: [ "<__algorithm/ranges_iterator_concept.h>", "private", "", "public" ] }, + { include: [ "<__algorithm/ranges_lexicographical_compare.h>", "private", "", "public" ] }, + { include: [ "<__algorithm/ranges_lower_bound.h>", "private", "", "public" ] }, + { include: [ "<__algorithm/ranges_make_heap.h>", "private", "", "public" ] }, + { include: [ "<__algorithm/ranges_max.h>", "private", "", "public" ] }, + { include: [ "<__algorithm/ranges_max_element.h>", "private", "", "public" ] }, + { include: [ "<__algorithm/ranges_merge.h>", "private", "", "public" ] }, + { include: [ "<__algorithm/ranges_min.h>", "private", "", "public" ] }, + { include: [ "<__algorithm/ranges_min_element.h>", "private", "", "public" ] }, + { include: [ "<__algorithm/ranges_minmax.h>", "private", "", "public" ] }, + { include: [ "<__algorithm/ranges_minmax_element.h>", "private", "", "public" ] }, + { include: [ "<__algorithm/ranges_mismatch.h>", "private", "", "public" ] }, + { include: [ "<__algorithm/ranges_move.h>", "private", "", "public" ] }, + { include: [ "<__algorithm/ranges_move_backward.h>", "private", "", "public" ] }, + { include: [ "<__algorithm/ranges_next_permutation.h>", "private", "", "public" ] }, + { include: [ "<__algorithm/ranges_none_of.h>", "private", "", "public" ] }, + { include: [ "<__algorithm/ranges_nth_element.h>", "private", "", "public" ] }, + { include: [ "<__algorithm/ranges_partial_sort.h>", "private", "", "public" ] }, + { include: [ "<__algorithm/ranges_partial_sort_copy.h>", "private", "", "public" ] }, + { include: [ "<__algorithm/ranges_partition.h>", "private", "", "public" ] }, + { include: [ "<__algorithm/ranges_partition_copy.h>", "private", "", "public" ] }, + { include: [ "<__algorithm/ranges_partition_point.h>", "private", "", "public" ] }, + { include: [ "<__algorithm/ranges_pop_heap.h>", "private", "", "public" ] }, + { include: [ "<__algorithm/ranges_prev_permutation.h>", "private", "", "public" ] }, + { include: [ "<__algorithm/ranges_push_heap.h>", "private", "", "public" ] }, + { include: [ "<__algorithm/ranges_remove.h>", "private", "", "public" ] }, + { include: [ "<__algorithm/ranges_remove_copy.h>", "private", "", "public" ] }, + { include: [ "<__algorithm/ranges_remove_copy_if.h>", "private", "", "public" ] }, + { include: [ "<__algorithm/ranges_remove_if.h>", "private", "", "public" ] }, + { include: [ "<__algorithm/ranges_replace.h>", "private", "", "public" ] }, + { include: [ "<__algorithm/ranges_replace_copy.h>", "private", "", "public" ] }, + { include: [ "<__algorithm/ranges_replace_copy_if.h>", "private", "", "public" ] }, + { include: [ "<__algorithm/ranges_replace_if.h>", "private", "", "public" ] }, + { include: [ "<__algorithm/ranges_reverse.h>", "private", "", "public" ] }, + { include: [ "<__algorithm/ranges_reverse_copy.h>", "private", "", "public" ] }, + { include: [ "<__algorithm/ranges_rotate.h>", "private", "", "public" ] }, + { include: [ "<__algorithm/ranges_rotate_copy.h>", "private", "", "public" ] }, + { include: [ "<__algorithm/ranges_sample.h>", "private", "", "public" ] }, + { include: [ "<__algorithm/ranges_search.h>", "private", "", "public" ] }, + { include: [ "<__algorithm/ranges_search_n.h>", "private", "", "public" ] }, + { include: [ "<__algorithm/ranges_set_difference.h>", "private", "", "public" ] }, + { include: [ "<__algorithm/ranges_set_intersection.h>", "private", "", "public" ] }, + { include: [ "<__algorithm/ranges_set_symmetric_difference.h>", "private", "", "public" ] }, + { include: [ "<__algorithm/ranges_set_union.h>", "private", "", "public" ] }, + { include: [ "<__algorithm/ranges_shuffle.h>", "private", "", "public" ] }, + { include: [ "<__algorithm/ranges_sort.h>", "private", "", "public" ] }, + { include: [ "<__algorithm/ranges_sort_heap.h>", "private", "", "public" ] }, + { include: [ "<__algorithm/ranges_stable_partition.h>", "private", "", "public" ] }, + { include: [ "<__algorithm/ranges_stable_sort.h>", "private", "", "public" ] }, + { include: [ "<__algorithm/ranges_starts_with.h>", "private", "", "public" ] }, + { include: [ "<__algorithm/ranges_swap_ranges.h>", "private", "", "public" ] }, + { include: [ "<__algorithm/ranges_transform.h>", "private", "", "public" ] }, + { include: [ "<__algorithm/ranges_unique.h>", "private", "", "public" ] }, + { include: [ "<__algorithm/ranges_unique_copy.h>", "private", "", "public" ] }, + { include: [ "<__algorithm/ranges_upper_bound.h>", "private", "", "public" ] }, + { include: [ "<__algorithm/remove.h>", "private", "", "public" ] }, + { include: [ "<__algorithm/remove_copy.h>", "private", "", "public" ] }, + { include: [ "<__algorithm/remove_copy_if.h>", "private", "", "public" ] }, + { include: [ "<__algorithm/remove_if.h>", "private", "", "public" ] }, + { include: [ "<__algorithm/replace.h>", "private", "", "public" ] }, + { include: [ "<__algorithm/replace_copy.h>", "private", "", "public" ] }, + { include: [ "<__algorithm/replace_copy_if.h>", "private", "", "public" ] }, + { include: [ "<__algorithm/replace_if.h>", "private", "", "public" ] }, + { include: [ "<__algorithm/reverse.h>", "private", "", "public" ] }, + { include: [ "<__algorithm/reverse_copy.h>", "private", "", "public" ] }, + { include: [ "<__algorithm/rotate.h>", "private", "", "public" ] }, + { include: [ "<__algorithm/rotate_copy.h>", "private", "", "public" ] }, + { include: [ "<__algorithm/sample.h>", "private", "", "public" ] }, + { include: [ "<__algorithm/search.h>", "private", "", "public" ] }, + { include: [ "<__algorithm/search_n.h>", "private", "", "public" ] }, + { include: [ "<__algorithm/set_difference.h>", "private", "", "public" ] }, + { include: [ "<__algorithm/set_intersection.h>", "private", "", "public" ] }, + { include: [ "<__algorithm/set_symmetric_difference.h>", "private", "", "public" ] }, + { include: [ "<__algorithm/set_union.h>", "private", "", "public" ] }, + { include: [ "<__algorithm/shift_left.h>", "private", "", "public" ] }, + { include: [ "<__algorithm/shift_right.h>", "private", "", "public" ] }, + { include: [ "<__algorithm/shuffle.h>", "private", "", "public" ] }, + { include: [ "<__algorithm/sift_down.h>", "private", "", "public" ] }, + { include: [ "<__algorithm/simd_utils.h>", "private", "", "public" ] }, + { include: [ "<__algorithm/sort.h>", "private", "", "public" ] }, + { include: [ "<__algorithm/sort_heap.h>", "private", "", "public" ] }, + { include: [ "<__algorithm/stable_partition.h>", "private", "", "public" ] }, + { include: [ "<__algorithm/stable_sort.h>", "private", "", "public" ] }, + { include: [ "<__algorithm/swap_ranges.h>", "private", "", "public" ] }, + { include: [ "<__algorithm/three_way_comp_ref_type.h>", "private", "", "public" ] }, + { include: [ "<__algorithm/transform.h>", "private", "", "public" ] }, + { include: [ "<__algorithm/uniform_random_bit_generator_adaptor.h>", "private", "", "public" ] }, + { include: [ "<__algorithm/unique.h>", "private", "", "public" ] }, + { include: [ "<__algorithm/unique_copy.h>", "private", "", "public" ] }, + { include: [ "<__algorithm/unwrap_iter.h>", "private", "", "public" ] }, + { include: [ "<__algorithm/unwrap_range.h>", "private", "", "public" ] }, + { include: [ "<__algorithm/upper_bound.h>", "private", "", "public" ] }, + { include: [ "<__atomic/aliases.h>", "private", "", "public" ] }, + { include: [ "<__atomic/atomic.h>", "private", "", "public" ] }, + { include: [ "<__atomic/atomic_base.h>", "private", "", "public" ] }, + { include: [ "<__atomic/atomic_flag.h>", "private", "", "public" ] }, + { include: [ "<__atomic/atomic_init.h>", "private", "", "public" ] }, + { include: [ "<__atomic/atomic_lock_free.h>", "private", "", "public" ] }, + { include: [ "<__atomic/atomic_ref.h>", "private", "", "public" ] }, + { include: [ "<__atomic/atomic_sync.h>", "private", "", "public" ] }, + { include: [ "<__atomic/check_memory_order.h>", "private", "", "public" ] }, + { include: [ "<__atomic/contention_t.h>", "private", "", "public" ] }, + { include: [ "<__atomic/cxx_atomic_impl.h>", "private", "", "public" ] }, + { include: [ "<__atomic/fence.h>", "private", "", "public" ] }, + { include: [ "<__atomic/is_always_lock_free.h>", "private", "", "public" ] }, + { include: [ "<__atomic/kill_dependency.h>", "private", "", "public" ] }, + { include: [ "<__atomic/memory_order.h>", "private", "", "public" ] }, + { include: [ "<__atomic/to_gcc_order.h>", "private", "", "public" ] }, + { include: [ "<__bit/bit_cast.h>", "private", "", "public" ] }, + { include: [ "<__bit/bit_ceil.h>", "private", "", "public" ] }, + { include: [ "<__bit/bit_floor.h>", "private", "", "public" ] }, + { include: [ "<__bit/bit_log2.h>", "private", "", "public" ] }, + { include: [ "<__bit/bit_width.h>", "private", "", "public" ] }, + { include: [ "<__bit/blsr.h>", "private", "", "public" ] }, + { include: [ "<__bit/byteswap.h>", "private", "", "public" ] }, + { include: [ "<__bit/countl.h>", "private", "", "public" ] }, + { include: [ "<__bit/countr.h>", "private", "", "public" ] }, + { include: [ "<__bit/endian.h>", "private", "", "public" ] }, + { include: [ "<__bit/has_single_bit.h>", "private", "", "public" ] }, + { include: [ "<__bit/invert_if.h>", "private", "", "public" ] }, + { include: [ "<__bit/popcount.h>", "private", "", "public" ] }, + { include: [ "<__bit/rotate.h>", "private", "", "public" ] }, + { include: [ "<__charconv/chars_format.h>", "private", "", "public" ] }, + { include: [ "<__charconv/from_chars_integral.h>", "private", "", "public" ] }, + { include: [ "<__charconv/from_chars_result.h>", "private", "", "public" ] }, + { include: [ "<__charconv/tables.h>", "private", "", "public" ] }, + { include: [ "<__charconv/to_chars.h>", "private", "", "public" ] }, + { include: [ "<__charconv/to_chars_base_10.h>", "private", "", "public" ] }, + { include: [ "<__charconv/to_chars_floating_point.h>", "private", "", "public" ] }, + { include: [ "<__charconv/to_chars_integral.h>", "private", "", "public" ] }, + { include: [ "<__charconv/to_chars_result.h>", "private", "", "public" ] }, + { include: [ "<__charconv/traits.h>", "private", "", "public" ] }, + { include: [ "<__chrono/calendar.h>", "private", "", "public" ] }, + { include: [ "<__chrono/concepts.h>", "private", "", "public" ] }, + { include: [ "<__chrono/convert_to_timespec.h>", "private", "", "public" ] }, + { include: [ "<__chrono/convert_to_tm.h>", "private", "", "public" ] }, + { include: [ "<__chrono/day.h>", "private", "", "public" ] }, + { include: [ "<__chrono/duration.h>", "private", "", "public" ] }, + { include: [ "<__chrono/file_clock.h>", "private", "", "public" ] }, + { include: [ "<__chrono/formatter.h>", "private", "", "public" ] }, + { include: [ "<__chrono/hh_mm_ss.h>", "private", "", "public" ] }, + { include: [ "<__chrono/high_resolution_clock.h>", "private", "", "public" ] }, + { include: [ "<__chrono/leap_second.h>", "private", "", "public" ] }, + { include: [ "<__chrono/literals.h>", "private", "", "public" ] }, + { include: [ "<__chrono/month.h>", "private", "", "public" ] }, + { include: [ "<__chrono/month_weekday.h>", "private", "", "public" ] }, + { include: [ "<__chrono/monthday.h>", "private", "", "public" ] }, + { include: [ "<__chrono/ostream.h>", "private", "", "public" ] }, + { include: [ "<__chrono/parser_std_format_spec.h>", "private", "", "public" ] }, + { include: [ "<__chrono/statically_widen.h>", "private", "", "public" ] }, + { include: [ "<__chrono/steady_clock.h>", "private", "", "public" ] }, + { include: [ "<__chrono/sys_info.h>", "private", "", "public" ] }, + { include: [ "<__chrono/system_clock.h>", "private", "", "public" ] }, + { include: [ "<__chrono/time_point.h>", "private", "", "public" ] }, + { include: [ "<__chrono/time_zone.h>", "private", "", "public" ] }, + { include: [ "<__chrono/time_zone_link.h>", "private", "", "public" ] }, + { include: [ "<__chrono/tzdb.h>", "private", "", "public" ] }, + { include: [ "<__chrono/tzdb_list.h>", "private", "", "public" ] }, + { include: [ "<__chrono/weekday.h>", "private", "", "public" ] }, + { include: [ "<__chrono/year.h>", "private", "", "public" ] }, + { include: [ "<__chrono/year_month.h>", "private", "", "public" ] }, + { include: [ "<__chrono/year_month_day.h>", "private", "", "public" ] }, + { include: [ "<__chrono/year_month_weekday.h>", "private", "", "public" ] }, + { include: [ "<__compare/common_comparison_category.h>", "private", "", "public" ] }, + { include: [ "<__compare/compare_partial_order_fallback.h>", "private", "", "public" ] }, + { include: [ "<__compare/compare_strong_order_fallback.h>", "private", "", "public" ] }, + { include: [ "<__compare/compare_three_way.h>", "private", "", "public" ] }, + { include: [ "<__compare/compare_three_way_result.h>", "private", "", "public" ] }, + { include: [ "<__compare/compare_weak_order_fallback.h>", "private", "", "public" ] }, + { include: [ "<__compare/is_eq.h>", "private", "", "public" ] }, + { include: [ "<__compare/ordering.h>", "private", "", "public" ] }, + { include: [ "<__compare/partial_order.h>", "private", "", "public" ] }, + { include: [ "<__compare/strong_order.h>", "private", "", "public" ] }, + { include: [ "<__compare/synth_three_way.h>", "private", "", "public" ] }, + { include: [ "<__compare/three_way_comparable.h>", "private", "", "public" ] }, + { include: [ "<__compare/weak_order.h>", "private", "", "public" ] }, + { include: [ "<__concepts/arithmetic.h>", "private", "", "public" ] }, + { include: [ "<__concepts/assignable.h>", "private", "", "public" ] }, + { include: [ "<__concepts/boolean_testable.h>", "private", "", "public" ] }, + { include: [ "<__concepts/class_or_enum.h>", "private", "", "public" ] }, + { include: [ "<__concepts/common_reference_with.h>", "private", "", "public" ] }, + { include: [ "<__concepts/common_with.h>", "private", "", "public" ] }, + { include: [ "<__concepts/constructible.h>", "private", "", "public" ] }, + { include: [ "<__concepts/convertible_to.h>", "private", "", "public" ] }, + { include: [ "<__concepts/copyable.h>", "private", "", "public" ] }, + { include: [ "<__concepts/derived_from.h>", "private", "", "public" ] }, + { include: [ "<__concepts/destructible.h>", "private", "", "public" ] }, + { include: [ "<__concepts/different_from.h>", "private", "", "public" ] }, + { include: [ "<__concepts/equality_comparable.h>", "private", "", "public" ] }, + { include: [ "<__concepts/invocable.h>", "private", "", "public" ] }, + { include: [ "<__concepts/movable.h>", "private", "", "public" ] }, + { include: [ "<__concepts/predicate.h>", "private", "", "public" ] }, + { include: [ "<__concepts/regular.h>", "private", "", "public" ] }, + { include: [ "<__concepts/relation.h>", "private", "", "public" ] }, + { include: [ "<__concepts/same_as.h>", "private", "", "public" ] }, + { include: [ "<__concepts/semiregular.h>", "private", "", "public" ] }, + { include: [ "<__concepts/swappable.h>", "private", "", "public" ] }, + { include: [ "<__concepts/totally_ordered.h>", "private", "", "public" ] }, + { include: [ "<__condition_variable/condition_variable.h>", "private", "", "public" ] }, + { include: [ "<__coroutine/coroutine_handle.h>", "private", "", "public" ] }, + { include: [ "<__coroutine/coroutine_traits.h>", "private", "", "public" ] }, + { include: [ "<__coroutine/noop_coroutine_handle.h>", "private", "", "public" ] }, + { include: [ "<__coroutine/trivial_awaitables.h>", "private", "", "public" ] }, + { include: [ "<__exception/exception.h>", "private", "", "public" ] }, + { include: [ "<__exception/exception_ptr.h>", "private", "", "public" ] }, + { include: [ "<__exception/nested_exception.h>", "private", "", "public" ] }, + { include: [ "<__exception/operations.h>", "private", "", "public" ] }, + { include: [ "<__exception/terminate.h>", "private", "", "public" ] }, + { include: [ "<__expected/bad_expected_access.h>", "private", "", "public" ] }, + { include: [ "<__expected/expected.h>", "private", "", "public" ] }, + { include: [ "<__expected/unexpect.h>", "private", "", "public" ] }, + { include: [ "<__expected/unexpected.h>", "private", "", "public" ] }, + { include: [ "<__filesystem/copy_options.h>", "private", "", "public" ] }, + { include: [ "<__filesystem/directory_entry.h>", "private", "", "public" ] }, + { include: [ "<__filesystem/directory_iterator.h>", "private", "", "public" ] }, + { include: [ "<__filesystem/directory_options.h>", "private", "", "public" ] }, + { include: [ "<__filesystem/file_status.h>", "private", "", "public" ] }, + { include: [ "<__filesystem/file_time_type.h>", "private", "", "public" ] }, + { include: [ "<__filesystem/file_type.h>", "private", "", "public" ] }, + { include: [ "<__filesystem/filesystem_error.h>", "private", "", "public" ] }, + { include: [ "<__filesystem/operations.h>", "private", "", "public" ] }, + { include: [ "<__filesystem/path.h>", "private", "", "public" ] }, + { include: [ "<__filesystem/path_iterator.h>", "private", "", "public" ] }, + { include: [ "<__filesystem/perm_options.h>", "private", "", "public" ] }, + { include: [ "<__filesystem/perms.h>", "private", "", "public" ] }, + { include: [ "<__filesystem/recursive_directory_iterator.h>", "private", "", "public" ] }, + { include: [ "<__filesystem/space_info.h>", "private", "", "public" ] }, + { include: [ "<__filesystem/u8path.h>", "private", "", "public" ] }, + { include: [ "<__format/buffer.h>", "private", "", "public" ] }, + { include: [ "<__format/concepts.h>", "private", "", "public" ] }, + { include: [ "<__format/container_adaptor.h>", "private", "", "public" ] }, + { include: [ "<__format/enable_insertable.h>", "private", "", "public" ] }, + { include: [ "<__format/escaped_output_table.h>", "private", "", "public" ] }, + { include: [ "<__format/extended_grapheme_cluster_table.h>", "private", "", "public" ] }, + { include: [ "<__format/format_arg.h>", "private", "", "public" ] }, + { include: [ "<__format/format_arg_store.h>", "private", "", "public" ] }, + { include: [ "<__format/format_args.h>", "private", "", "public" ] }, + { include: [ "<__format/format_context.h>", "private", "", "public" ] }, + { include: [ "<__format/format_error.h>", "private", "", "public" ] }, + { include: [ "<__format/format_functions.h>", "private", "", "public" ] }, + { include: [ "<__format/format_parse_context.h>", "private", "", "public" ] }, + { include: [ "<__format/format_string.h>", "private", "", "public" ] }, + { include: [ "<__format/format_to_n_result.h>", "private", "", "public" ] }, + { include: [ "<__format/formatter.h>", "private", "", "public" ] }, + { include: [ "<__format/formatter_bool.h>", "private", "", "public" ] }, + { include: [ "<__format/formatter_char.h>", "private", "", "public" ] }, + { include: [ "<__format/formatter_floating_point.h>", "private", "", "public" ] }, + { include: [ "<__format/formatter_integer.h>", "private", "", "public" ] }, + { include: [ "<__format/formatter_integral.h>", "private", "", "public" ] }, + { include: [ "<__format/formatter_output.h>", "private", "", "public" ] }, + { include: [ "<__format/formatter_pointer.h>", "private", "", "public" ] }, + { include: [ "<__format/formatter_string.h>", "private", "", "public" ] }, + { include: [ "<__format/formatter_tuple.h>", "private", "", "public" ] }, + { include: [ "<__format/indic_conjunct_break_table.h>", "private", "", "public" ] }, + { include: [ "<__format/parser_std_format_spec.h>", "private", "", "public" ] }, + { include: [ "<__format/range_default_formatter.h>", "private", "", "public" ] }, + { include: [ "<__format/range_formatter.h>", "private", "", "public" ] }, + { include: [ "<__format/unicode.h>", "private", "", "public" ] }, + { include: [ "<__format/width_estimation_table.h>", "private", "", "public" ] }, + { include: [ "<__format/write_escaped.h>", "private", "", "public" ] }, + { include: [ "<__functional/binary_function.h>", "private", "", "public" ] }, + { include: [ "<__functional/binary_negate.h>", "private", "", "public" ] }, + { include: [ "<__functional/bind.h>", "private", "", "public" ] }, + { include: [ "<__functional/bind_back.h>", "private", "", "public" ] }, + { include: [ "<__functional/bind_front.h>", "private", "", "public" ] }, + { include: [ "<__functional/binder1st.h>", "private", "", "public" ] }, + { include: [ "<__functional/binder2nd.h>", "private", "", "public" ] }, + { include: [ "<__functional/boyer_moore_searcher.h>", "private", "", "public" ] }, + { include: [ "<__functional/compose.h>", "private", "", "public" ] }, + { include: [ "<__functional/default_searcher.h>", "private", "", "public" ] }, + { include: [ "<__functional/function.h>", "private", "", "public" ] }, + { include: [ "<__functional/hash.h>", "private", "", "public" ] }, + { include: [ "<__functional/identity.h>", "private", "", "public" ] }, + { include: [ "<__functional/invoke.h>", "private", "", "public" ] }, + { include: [ "<__functional/is_transparent.h>", "private", "", "public" ] }, + { include: [ "<__functional/mem_fn.h>", "private", "", "public" ] }, + { include: [ "<__functional/mem_fun_ref.h>", "private", "", "public" ] }, + { include: [ "<__functional/not_fn.h>", "private", "", "public" ] }, + { include: [ "<__functional/operations.h>", "private", "", "public" ] }, + { include: [ "<__functional/perfect_forward.h>", "private", "", "public" ] }, + { include: [ "<__functional/pointer_to_binary_function.h>", "private", "", "public" ] }, + { include: [ "<__functional/pointer_to_unary_function.h>", "private", "", "public" ] }, + { include: [ "<__functional/ranges_operations.h>", "private", "", "public" ] }, + { include: [ "<__functional/reference_wrapper.h>", "private", "", "public" ] }, + { include: [ "<__functional/unary_function.h>", "private", "", "public" ] }, + { include: [ "<__functional/unary_negate.h>", "private", "", "public" ] }, + { include: [ "<__functional/weak_result_type.h>", "private", "", "public" ] }, + { include: [ "<__fwd/array.h>", "private", "", "public" ] }, + { include: [ "<__fwd/bit_reference.h>", "private", "", "public" ] }, + { include: [ "<__fwd/bit_reference.h>", "private", "", "public" ] }, + { include: [ "<__fwd/complex.h>", "private", "", "public" ] }, + { include: [ "<__fwd/deque.h>", "private", "", "public" ] }, + { include: [ "<__fwd/format.h>", "private", "", "public" ] }, + { include: [ "<__fwd/fstream.h>", "private", "", "public" ] }, + { include: [ "<__fwd/functional.h>", "private", "", "public" ] }, + { include: [ "<__fwd/ios.h>", "private", "", "public" ] }, + { include: [ "<__fwd/istream.h>", "private", "", "public" ] }, + { include: [ "<__fwd/mdspan.h>", "private", "", "public" ] }, + { include: [ "<__fwd/memory.h>", "private", "", "public" ] }, + { include: [ "<__fwd/memory_resource.h>", "private", "", "public" ] }, + { include: [ "<__fwd/ostream.h>", "private", "", "public" ] }, + { include: [ "<__fwd/pair.h>", "private", "", "public" ] }, + { include: [ "<__fwd/queue.h>", "private", "", "public" ] }, + { include: [ "<__fwd/span.h>", "private", "", "public" ] }, + { include: [ "<__fwd/sstream.h>", "private", "", "public" ] }, + { include: [ "<__fwd/stack.h>", "private", "", "public" ] }, + { include: [ "<__fwd/streambuf.h>", "private", "", "public" ] }, + { include: [ "<__fwd/string.h>", "private", "", "public" ] }, + { include: [ "<__fwd/string_view.h>", "private", "", "public" ] }, + { include: [ "<__fwd/subrange.h>", "private", "", "public" ] }, + { include: [ "<__fwd/tuple.h>", "private", "", "public" ] }, + { include: [ "<__fwd/vector.h>", "private", "", "public" ] }, + { include: [ "<__ios/fpos.h>", "private", "", "public" ] }, + { include: [ "<__iterator/access.h>", "private", "", "public" ] }, + { include: [ "<__iterator/advance.h>", "private", "", "public" ] }, + { include: [ "<__iterator/back_insert_iterator.h>", "private", "", "public" ] }, + { include: [ "<__iterator/bounded_iter.h>", "private", "", "public" ] }, + { include: [ "<__iterator/common_iterator.h>", "private", "", "public" ] }, + { include: [ "<__iterator/concepts.h>", "private", "", "public" ] }, + { include: [ "<__iterator/counted_iterator.h>", "private", "", "public" ] }, + { include: [ "<__iterator/cpp17_iterator_concepts.h>", "private", "", "public" ] }, + { include: [ "<__iterator/data.h>", "private", "", "public" ] }, + { include: [ "<__iterator/default_sentinel.h>", "private", "", "public" ] }, + { include: [ "<__iterator/distance.h>", "private", "", "public" ] }, + { include: [ "<__iterator/empty.h>", "private", "", "public" ] }, + { include: [ "<__iterator/erase_if_container.h>", "private", "", "public" ] }, + { include: [ "<__iterator/front_insert_iterator.h>", "private", "", "public" ] }, + { include: [ "<__iterator/incrementable_traits.h>", "private", "", "public" ] }, + { include: [ "<__iterator/indirectly_comparable.h>", "private", "", "public" ] }, + { include: [ "<__iterator/insert_iterator.h>", "private", "", "public" ] }, + { include: [ "<__iterator/istream_iterator.h>", "private", "", "public" ] }, + { include: [ "<__iterator/istreambuf_iterator.h>", "private", "", "public" ] }, + { include: [ "<__iterator/iter_move.h>", "private", "", "public" ] }, + { include: [ "<__iterator/iter_swap.h>", "private", "", "public" ] }, + { include: [ "<__iterator/iterator.h>", "private", "", "public" ] }, + { include: [ "<__iterator/iterator_traits.h>", "private", "", "public" ] }, + { include: [ "<__iterator/iterator_with_data.h>", "private", "", "public" ] }, + { include: [ "<__iterator/mergeable.h>", "private", "", "public" ] }, + { include: [ "<__iterator/move_iterator.h>", "private", "", "public" ] }, + { include: [ "<__iterator/move_sentinel.h>", "private", "", "public" ] }, + { include: [ "<__iterator/next.h>", "private", "", "public" ] }, + { include: [ "<__iterator/ostream_iterator.h>", "private", "", "public" ] }, + { include: [ "<__iterator/ostreambuf_iterator.h>", "private", "", "public" ] }, + { include: [ "<__iterator/permutable.h>", "private", "", "public" ] }, + { include: [ "<__iterator/prev.h>", "private", "", "public" ] }, + { include: [ "<__iterator/projected.h>", "private", "", "public" ] }, + { include: [ "<__iterator/ranges_iterator_traits.h>", "private", "", "public" ] }, + { include: [ "<__iterator/readable_traits.h>", "private", "", "public" ] }, + { include: [ "<__iterator/reverse_access.h>", "private", "", "public" ] }, + { include: [ "<__iterator/reverse_iterator.h>", "private", "", "public" ] }, + { include: [ "<__iterator/segmented_iterator.h>", "private", "", "public" ] }, + { include: [ "<__iterator/size.h>", "private", "", "public" ] }, + { include: [ "<__iterator/sortable.h>", "private", "", "public" ] }, + { include: [ "<__iterator/unreachable_sentinel.h>", "private", "", "public" ] }, + { include: [ "<__iterator/wrap_iter.h>", "private", "", "public" ] }, + { include: [ "<__locale_dir/locale_base_api.h>", "private", "", "public" ] }, + { include: [ "<__locale_dir/locale_base_api/android.h>", "private", "", "public" ] }, + { include: [ "<__locale_dir/locale_base_api/bsd_locale_defaults.h>", "private", "", "public" ] }, + { include: [ "<__locale_dir/locale_base_api/bsd_locale_fallbacks.h>", "private", "", "public" ] }, + { include: [ "<__locale_dir/locale_base_api/fuchsia.h>", "private", "", "public" ] }, + { include: [ "<__locale_dir/locale_base_api/ibm.h>", "private", "", "public" ] }, + { include: [ "<__locale_dir/locale_base_api/locale_guard.h>", "private", "", "public" ] }, + { include: [ "<__locale_dir/locale_base_api/musl.h>", "private", "", "public" ] }, + { include: [ "<__locale_dir/locale_base_api/newlib.h>", "private", "", "public" ] }, + { include: [ "<__locale_dir/locale_base_api/openbsd.h>", "private", "", "public" ] }, + { include: [ "<__locale_dir/locale_base_api/win32.h>", "private", "", "public" ] }, + { include: [ "<__math/abs.h>", "private", "", "public" ] }, + { include: [ "<__math/copysign.h>", "private", "", "public" ] }, + { include: [ "<__math/error_functions.h>", "private", "", "public" ] }, + { include: [ "<__math/exponential_functions.h>", "private", "", "public" ] }, + { include: [ "<__math/fdim.h>", "private", "", "public" ] }, + { include: [ "<__math/fma.h>", "private", "", "public" ] }, + { include: [ "<__math/gamma.h>", "private", "", "public" ] }, + { include: [ "<__math/hyperbolic_functions.h>", "private", "", "public" ] }, + { include: [ "<__math/hypot.h>", "private", "", "public" ] }, + { include: [ "<__math/inverse_hyperbolic_functions.h>", "private", "", "public" ] }, + { include: [ "<__math/inverse_trigonometric_functions.h>", "private", "", "public" ] }, + { include: [ "<__math/logarithms.h>", "private", "", "public" ] }, + { include: [ "<__math/min_max.h>", "private", "", "public" ] }, + { include: [ "<__math/modulo.h>", "private", "", "public" ] }, + { include: [ "<__math/remainder.h>", "private", "", "public" ] }, + { include: [ "<__math/roots.h>", "private", "", "public" ] }, + { include: [ "<__math/rounding_functions.h>", "private", "", "public" ] }, + { include: [ "<__math/traits.h>", "private", "", "public" ] }, + { include: [ "<__math/trigonometric_functions.h>", "private", "", "public" ] }, + { include: [ "<__mdspan/default_accessor.h>", "private", "", "public" ] }, + { include: [ "<__mdspan/extents.h>", "private", "", "public" ] }, + { include: [ "<__mdspan/layout_left.h>", "private", "", "public" ] }, + { include: [ "<__mdspan/layout_right.h>", "private", "", "public" ] }, + { include: [ "<__mdspan/layout_stride.h>", "private", "", "public" ] }, + { include: [ "<__mdspan/mdspan.h>", "private", "", "public" ] }, + { include: [ "<__memory/addressof.h>", "private", "", "public" ] }, + { include: [ "<__memory/align.h>", "private", "", "public" ] }, + { include: [ "<__memory/aligned_alloc.h>", "private", "", "public" ] }, + { include: [ "<__memory/allocate_at_least.h>", "private", "", "public" ] }, + { include: [ "<__memory/allocation_guard.h>", "private", "", "public" ] }, + { include: [ "<__memory/allocator.h>", "private", "", "public" ] }, + { include: [ "<__memory/allocator_arg_t.h>", "private", "", "public" ] }, + { include: [ "<__memory/allocator_destructor.h>", "private", "", "public" ] }, + { include: [ "<__memory/allocator_traits.h>", "private", "", "public" ] }, + { include: [ "<__memory/assume_aligned.h>", "private", "", "public" ] }, + { include: [ "<__memory/auto_ptr.h>", "private", "", "public" ] }, + { include: [ "<__memory/builtin_new_allocator.h>", "private", "", "public" ] }, + { include: [ "<__memory/compressed_pair.h>", "private", "", "public" ] }, + { include: [ "<__memory/concepts.h>", "private", "", "public" ] }, + { include: [ "<__memory/construct_at.h>", "private", "", "public" ] }, + { include: [ "<__memory/destruct_n.h>", "private", "", "public" ] }, + { include: [ "<__memory/pointer_traits.h>", "private", "", "public" ] }, + { include: [ "<__memory/ranges_construct_at.h>", "private", "", "public" ] }, + { include: [ "<__memory/ranges_uninitialized_algorithms.h>", "private", "", "public" ] }, + { include: [ "<__memory/raw_storage_iterator.h>", "private", "", "public" ] }, + { include: [ "<__memory/shared_ptr.h>", "private", "", "public" ] }, + { include: [ "<__memory/swap_allocator.h>", "private", "", "public" ] }, + { include: [ "<__memory/temp_value.h>", "private", "", "public" ] }, + { include: [ "<__memory/temporary_buffer.h>", "private", "", "public" ] }, + { include: [ "<__memory/uninitialized_algorithms.h>", "private", "", "public" ] }, + { include: [ "<__memory/unique_ptr.h>", "private", "", "public" ] }, + { include: [ "<__memory/uses_allocator.h>", "private", "", "public" ] }, + { include: [ "<__memory/uses_allocator_construction.h>", "private", "", "public" ] }, + { include: [ "<__memory/voidify.h>", "private", "", "public" ] }, + { include: [ "<__memory_resource/memory_resource.h>", "private", "", "public" ] }, + { include: [ "<__memory_resource/monotonic_buffer_resource.h>", "private", "", "public" ] }, + { include: [ "<__memory_resource/polymorphic_allocator.h>", "private", "", "public" ] }, + { include: [ "<__memory_resource/pool_options.h>", "private", "", "public" ] }, + { include: [ "<__memory_resource/synchronized_pool_resource.h>", "private", "", "public" ] }, + { include: [ "<__memory_resource/unsynchronized_pool_resource.h>", "private", "", "public" ] }, + { include: [ "<__mutex/lock_guard.h>", "private", "", "public" ] }, + { include: [ "<__mutex/mutex.h>", "private", "", "public" ] }, + { include: [ "<__mutex/once_flag.h>", "private", "", "public" ] }, + { include: [ "<__mutex/tag_types.h>", "private", "", "public" ] }, + { include: [ "<__mutex/unique_lock.h>", "private", "", "public" ] }, + { include: [ "<__numeric/accumulate.h>", "private", "", "public" ] }, + { include: [ "<__numeric/adjacent_difference.h>", "private", "", "public" ] }, + { include: [ "<__numeric/exclusive_scan.h>", "private", "", "public" ] }, + { include: [ "<__numeric/gcd_lcm.h>", "private", "", "public" ] }, + { include: [ "<__numeric/inclusive_scan.h>", "private", "", "public" ] }, + { include: [ "<__numeric/inner_product.h>", "private", "", "public" ] }, + { include: [ "<__numeric/iota.h>", "private", "", "public" ] }, + { include: [ "<__numeric/midpoint.h>", "private", "", "public" ] }, + { include: [ "<__numeric/partial_sum.h>", "private", "", "public" ] }, + { include: [ "<__numeric/pstl_reduce.h>", "private", "", "public" ] }, + { include: [ "<__numeric/pstl_transform_reduce.h>", "private", "", "public" ] }, + { include: [ "<__numeric/reduce.h>", "private", "", "public" ] }, + { include: [ "<__numeric/saturation_arithmetic.h>", "private", "", "public" ] }, + { include: [ "<__numeric/transform_exclusive_scan.h>", "private", "", "public" ] }, + { include: [ "<__numeric/transform_inclusive_scan.h>", "private", "", "public" ] }, + { include: [ "<__numeric/transform_reduce.h>", "private", "", "public" ] }, + { include: [ "<__random/bernoulli_distribution.h>", "private", "", "public" ] }, + { include: [ "<__random/binomial_distribution.h>", "private", "", "public" ] }, + { include: [ "<__random/cauchy_distribution.h>", "private", "", "public" ] }, + { include: [ "<__random/chi_squared_distribution.h>", "private", "", "public" ] }, + { include: [ "<__random/clamp_to_integral.h>", "private", "", "public" ] }, + { include: [ "<__random/default_random_engine.h>", "private", "", "public" ] }, + { include: [ "<__random/discard_block_engine.h>", "private", "", "public" ] }, + { include: [ "<__random/discrete_distribution.h>", "private", "", "public" ] }, + { include: [ "<__random/exponential_distribution.h>", "private", "", "public" ] }, + { include: [ "<__random/extreme_value_distribution.h>", "private", "", "public" ] }, + { include: [ "<__random/fisher_f_distribution.h>", "private", "", "public" ] }, + { include: [ "<__random/gamma_distribution.h>", "private", "", "public" ] }, + { include: [ "<__random/generate_canonical.h>", "private", "", "public" ] }, + { include: [ "<__random/geometric_distribution.h>", "private", "", "public" ] }, + { include: [ "<__random/independent_bits_engine.h>", "private", "", "public" ] }, + { include: [ "<__random/is_seed_sequence.h>", "private", "", "public" ] }, + { include: [ "<__random/is_valid.h>", "private", "", "public" ] }, + { include: [ "<__random/knuth_b.h>", "private", "", "public" ] }, + { include: [ "<__random/linear_congruential_engine.h>", "private", "", "public" ] }, + { include: [ "<__random/log2.h>", "private", "", "public" ] }, + { include: [ "<__random/lognormal_distribution.h>", "private", "", "public" ] }, + { include: [ "<__random/mersenne_twister_engine.h>", "private", "", "public" ] }, + { include: [ "<__random/negative_binomial_distribution.h>", "private", "", "public" ] }, + { include: [ "<__random/normal_distribution.h>", "private", "", "public" ] }, + { include: [ "<__random/piecewise_constant_distribution.h>", "private", "", "public" ] }, + { include: [ "<__random/piecewise_linear_distribution.h>", "private", "", "public" ] }, + { include: [ "<__random/poisson_distribution.h>", "private", "", "public" ] }, + { include: [ "<__random/random_device.h>", "private", "", "public" ] }, + { include: [ "<__random/ranlux.h>", "private", "", "public" ] }, + { include: [ "<__random/seed_seq.h>", "private", "", "public" ] }, + { include: [ "<__random/shuffle_order_engine.h>", "private", "", "public" ] }, + { include: [ "<__random/student_t_distribution.h>", "private", "", "public" ] }, + { include: [ "<__random/subtract_with_carry_engine.h>", "private", "", "public" ] }, + { include: [ "<__random/uniform_int_distribution.h>", "private", "", "public" ] }, + { include: [ "<__random/uniform_random_bit_generator.h>", "private", "", "public" ] }, + { include: [ "<__random/uniform_real_distribution.h>", "private", "", "public" ] }, + { include: [ "<__random/weibull_distribution.h>", "private", "", "public" ] }, + { include: [ "<__ranges/access.h>", "private", "", "public" ] }, + { include: [ "<__ranges/all.h>", "private", "", "public" ] }, + { include: [ "<__ranges/as_rvalue_view.h>", "private", "", "public" ] }, + { include: [ "<__ranges/chunk_by_view.h>", "private", "", "public" ] }, + { include: [ "<__ranges/common_view.h>", "private", "", "public" ] }, + { include: [ "<__ranges/concepts.h>", "private", "", "public" ] }, + { include: [ "<__ranges/container_compatible_range.h>", "private", "", "public" ] }, + { include: [ "<__ranges/counted.h>", "private", "", "public" ] }, + { include: [ "<__ranges/dangling.h>", "private", "", "public" ] }, + { include: [ "<__ranges/data.h>", "private", "", "public" ] }, + { include: [ "<__ranges/drop_view.h>", "private", "", "public" ] }, + { include: [ "<__ranges/drop_while_view.h>", "private", "", "public" ] }, + { include: [ "<__ranges/elements_view.h>", "private", "", "public" ] }, + { include: [ "<__ranges/empty.h>", "private", "", "public" ] }, + { include: [ "<__ranges/empty_view.h>", "private", "", "public" ] }, + { include: [ "<__ranges/enable_borrowed_range.h>", "private", "", "public" ] }, + { include: [ "<__ranges/enable_view.h>", "private", "", "public" ] }, + { include: [ "<__ranges/filter_view.h>", "private", "", "public" ] }, + { include: [ "<__ranges/from_range.h>", "private", "", "public" ] }, + { include: [ "<__ranges/iota_view.h>", "private", "", "public" ] }, + { include: [ "<__ranges/istream_view.h>", "private", "", "public" ] }, + { include: [ "<__ranges/join_view.h>", "private", "", "public" ] }, + { include: [ "<__ranges/lazy_split_view.h>", "private", "", "public" ] }, + { include: [ "<__ranges/movable_box.h>", "private", "", "public" ] }, + { include: [ "<__ranges/non_propagating_cache.h>", "private", "", "public" ] }, + { include: [ "<__ranges/owning_view.h>", "private", "", "public" ] }, + { include: [ "<__ranges/range_adaptor.h>", "private", "", "public" ] }, + { include: [ "<__ranges/rbegin.h>", "private", "", "public" ] }, + { include: [ "<__ranges/ref_view.h>", "private", "", "public" ] }, + { include: [ "<__ranges/rend.h>", "private", "", "public" ] }, + { include: [ "<__ranges/repeat_view.h>", "private", "", "public" ] }, + { include: [ "<__ranges/reverse_view.h>", "private", "", "public" ] }, + { include: [ "<__ranges/single_view.h>", "private", "", "public" ] }, + { include: [ "<__ranges/size.h>", "private", "", "public" ] }, + { include: [ "<__ranges/split_view.h>", "private", "", "public" ] }, + { include: [ "<__ranges/subrange.h>", "private", "", "public" ] }, + { include: [ "<__ranges/take_view.h>", "private", "", "public" ] }, + { include: [ "<__ranges/take_while_view.h>", "private", "", "public" ] }, + { include: [ "<__ranges/to.h>", "private", "", "public" ] }, + { include: [ "<__ranges/transform_view.h>", "private", "", "public" ] }, + { include: [ "<__ranges/view_interface.h>", "private", "", "public" ] }, + { include: [ "<__ranges/views.h>", "private", "", "public" ] }, + { include: [ "<__ranges/zip_view.h>", "private", "", "public" ] }, + { include: [ "<__stop_token/atomic_unique_lock.h>", "private", "", "public" ] }, + { include: [ "<__stop_token/intrusive_list_view.h>", "private", "", "public" ] }, + { include: [ "<__stop_token/intrusive_shared_ptr.h>", "private", "", "public" ] }, + { include: [ "<__stop_token/stop_callback.h>", "private", "", "public" ] }, + { include: [ "<__stop_token/stop_source.h>", "private", "", "public" ] }, + { include: [ "<__stop_token/stop_state.h>", "private", "", "public" ] }, + { include: [ "<__stop_token/stop_token.h>", "private", "", "public" ] }, + { include: [ "<__string/char_traits.h>", "private", "", "public" ] }, + { include: [ "<__string/constexpr_c_functions.h>", "private", "", "public" ] }, + { include: [ "<__string/extern_template_lists.h>", "private", "", "public" ] }, + { include: [ "<__system_error/errc.h>", "private", "", "public" ] }, + { include: [ "<__system_error/error_category.h>", "private", "", "public" ] }, + { include: [ "<__system_error/error_code.h>", "private", "", "public" ] }, + { include: [ "<__system_error/error_condition.h>", "private", "", "public" ] }, + { include: [ "<__system_error/system_error.h>", "private", "", "public" ] }, + { include: [ "<__thread/formatter.h>", "private", "", "public" ] }, + { include: [ "<__thread/id.h>", "private", "", "public" ] }, + { include: [ "<__thread/jthread.h>", "private", "", "public" ] }, + { include: [ "<__thread/poll_with_backoff.h>", "private", "", "public" ] }, + { include: [ "<__thread/support.h>", "private", "", "public" ] }, + { include: [ "<__thread/support.h>", "private", "", "public" ] }, + { include: [ "<__thread/support.h>", "private", "", "public" ] }, + { include: [ "<__thread/support.h>", "private", "", "public" ] }, + { include: [ "<__thread/support/c11.h>", "private", "", "public" ] }, + { include: [ "<__thread/support/c11.h>", "private", "", "public" ] }, + { include: [ "<__thread/support/c11.h>", "private", "", "public" ] }, + { include: [ "<__thread/support/c11.h>", "private", "", "public" ] }, + { include: [ "<__thread/support/external.h>", "private", "", "public" ] }, + { include: [ "<__thread/support/external.h>", "private", "", "public" ] }, + { include: [ "<__thread/support/external.h>", "private", "", "public" ] }, + { include: [ "<__thread/support/external.h>", "private", "", "public" ] }, + { include: [ "<__thread/support/pthread.h>", "private", "", "public" ] }, + { include: [ "<__thread/support/pthread.h>", "private", "", "public" ] }, + { include: [ "<__thread/support/pthread.h>", "private", "", "public" ] }, + { include: [ "<__thread/support/pthread.h>", "private", "", "public" ] }, + { include: [ "<__thread/support/windows.h>", "private", "", "public" ] }, + { include: [ "<__thread/support/windows.h>", "private", "", "public" ] }, + { include: [ "<__thread/support/windows.h>", "private", "", "public" ] }, + { include: [ "<__thread/support/windows.h>", "private", "", "public" ] }, + { include: [ "<__thread/this_thread.h>", "private", "", "public" ] }, + { include: [ "<__thread/thread.h>", "private", "", "public" ] }, + { include: [ "<__thread/timed_backoff_policy.h>", "private", "", "public" ] }, + { include: [ "<__tuple/find_index.h>", "private", "", "public" ] }, + { include: [ "<__tuple/make_tuple_types.h>", "private", "", "public" ] }, + { include: [ "<__tuple/sfinae_helpers.h>", "private", "", "public" ] }, + { include: [ "<__tuple/tuple_element.h>", "private", "", "public" ] }, + { include: [ "<__tuple/tuple_indices.h>", "private", "", "public" ] }, + { include: [ "<__tuple/tuple_like.h>", "private", "", "public" ] }, + { include: [ "<__tuple/tuple_like_ext.h>", "private", "", "public" ] }, + { include: [ "<__tuple/tuple_like_no_subrange.h>", "private", "", "public" ] }, + { include: [ "<__tuple/tuple_size.h>", "private", "", "public" ] }, + { include: [ "<__tuple/tuple_types.h>", "private", "", "public" ] }, + { include: [ "<__type_traits/add_const.h>", "private", "", "public" ] }, + { include: [ "<__type_traits/add_cv.h>", "private", "", "public" ] }, + { include: [ "<__type_traits/add_lvalue_reference.h>", "private", "", "public" ] }, + { include: [ "<__type_traits/add_pointer.h>", "private", "", "public" ] }, + { include: [ "<__type_traits/add_rvalue_reference.h>", "private", "", "public" ] }, + { include: [ "<__type_traits/add_volatile.h>", "private", "", "public" ] }, + { include: [ "<__type_traits/aligned_storage.h>", "private", "", "public" ] }, + { include: [ "<__type_traits/aligned_union.h>", "private", "", "public" ] }, + { include: [ "<__type_traits/alignment_of.h>", "private", "", "public" ] }, + { include: [ "<__type_traits/apply_cv.h>", "private", "", "public" ] }, + { include: [ "<__type_traits/can_extract_key.h>", "private", "", "public" ] }, + { include: [ "<__type_traits/common_reference.h>", "private", "", "public" ] }, + { include: [ "<__type_traits/common_type.h>", "private", "", "public" ] }, + { include: [ "<__type_traits/conditional.h>", "private", "", "public" ] }, + { include: [ "<__type_traits/conjunction.h>", "private", "", "public" ] }, + { include: [ "<__type_traits/copy_cv.h>", "private", "", "public" ] }, + { include: [ "<__type_traits/copy_cvref.h>", "private", "", "public" ] }, + { include: [ "<__type_traits/datasizeof.h>", "private", "", "public" ] }, + { include: [ "<__type_traits/decay.h>", "private", "", "public" ] }, + { include: [ "<__type_traits/dependent_type.h>", "private", "", "public" ] }, + { include: [ "<__type_traits/desugars_to.h>", "private", "", "public" ] }, + { include: [ "<__type_traits/disjunction.h>", "private", "", "public" ] }, + { include: [ "<__type_traits/enable_if.h>", "private", "", "public" ] }, + { include: [ "<__type_traits/extent.h>", "private", "", "public" ] }, + { include: [ "<__type_traits/has_unique_object_representation.h>", "private", "", "public" ] }, + { include: [ "<__type_traits/has_virtual_destructor.h>", "private", "", "public" ] }, + { include: [ "<__type_traits/integral_constant.h>", "private", "", "public" ] }, + { include: [ "<__type_traits/invoke.h>", "private", "", "public" ] }, + { include: [ "<__type_traits/is_abstract.h>", "private", "", "public" ] }, + { include: [ "<__type_traits/is_aggregate.h>", "private", "", "public" ] }, + { include: [ "<__type_traits/is_allocator.h>", "private", "", "public" ] }, + { include: [ "<__type_traits/is_always_bitcastable.h>", "private", "", "public" ] }, + { include: [ "<__type_traits/is_arithmetic.h>", "private", "", "public" ] }, + { include: [ "<__type_traits/is_array.h>", "private", "", "public" ] }, + { include: [ "<__type_traits/is_assignable.h>", "private", "", "public" ] }, + { include: [ "<__type_traits/is_base_of.h>", "private", "", "public" ] }, + { include: [ "<__type_traits/is_bounded_array.h>", "private", "", "public" ] }, + { include: [ "<__type_traits/is_callable.h>", "private", "", "public" ] }, + { include: [ "<__type_traits/is_char_like_type.h>", "private", "", "public" ] }, + { include: [ "<__type_traits/is_class.h>", "private", "", "public" ] }, + { include: [ "<__type_traits/is_compound.h>", "private", "", "public" ] }, + { include: [ "<__type_traits/is_const.h>", "private", "", "public" ] }, + { include: [ "<__type_traits/is_constant_evaluated.h>", "private", "", "public" ] }, + { include: [ "<__type_traits/is_constructible.h>", "private", "", "public" ] }, + { include: [ "<__type_traits/is_convertible.h>", "private", "", "public" ] }, + { include: [ "<__type_traits/is_core_convertible.h>", "private", "", "public" ] }, + { include: [ "<__type_traits/is_destructible.h>", "private", "", "public" ] }, + { include: [ "<__type_traits/is_empty.h>", "private", "", "public" ] }, + { include: [ "<__type_traits/is_enum.h>", "private", "", "public" ] }, + { include: [ "<__type_traits/is_equality_comparable.h>", "private", "", "public" ] }, + { include: [ "<__type_traits/is_execution_policy.h>", "private", "", "public" ] }, + { include: [ "<__type_traits/is_final.h>", "private", "", "public" ] }, + { include: [ "<__type_traits/is_floating_point.h>", "private", "", "public" ] }, + { include: [ "<__type_traits/is_function.h>", "private", "", "public" ] }, + { include: [ "<__type_traits/is_fundamental.h>", "private", "", "public" ] }, + { include: [ "<__type_traits/is_implicitly_default_constructible.h>", "private", "", "public" ] }, + { include: [ "<__type_traits/is_integral.h>", "private", "", "public" ] }, + { include: [ "<__type_traits/is_literal_type.h>", "private", "", "public" ] }, + { include: [ "<__type_traits/is_member_function_pointer.h>", "private", "", "public" ] }, + { include: [ "<__type_traits/is_member_object_pointer.h>", "private", "", "public" ] }, + { include: [ "<__type_traits/is_member_pointer.h>", "private", "", "public" ] }, + { include: [ "<__type_traits/is_nothrow_assignable.h>", "private", "", "public" ] }, + { include: [ "<__type_traits/is_nothrow_constructible.h>", "private", "", "public" ] }, + { include: [ "<__type_traits/is_nothrow_convertible.h>", "private", "", "public" ] }, + { include: [ "<__type_traits/is_nothrow_destructible.h>", "private", "", "public" ] }, + { include: [ "<__type_traits/is_null_pointer.h>", "private", "", "public" ] }, + { include: [ "<__type_traits/is_object.h>", "private", "", "public" ] }, + { include: [ "<__type_traits/is_pod.h>", "private", "", "public" ] }, + { include: [ "<__type_traits/is_pointer.h>", "private", "", "public" ] }, + { include: [ "<__type_traits/is_polymorphic.h>", "private", "", "public" ] }, + { include: [ "<__type_traits/is_primary_template.h>", "private", "", "public" ] }, + { include: [ "<__type_traits/is_reference.h>", "private", "", "public" ] }, + { include: [ "<__type_traits/is_reference_wrapper.h>", "private", "", "public" ] }, + { include: [ "<__type_traits/is_referenceable.h>", "private", "", "public" ] }, + { include: [ "<__type_traits/is_same.h>", "private", "", "public" ] }, + { include: [ "<__type_traits/is_scalar.h>", "private", "", "public" ] }, + { include: [ "<__type_traits/is_scoped_enum.h>", "private", "", "public" ] }, + { include: [ "<__type_traits/is_signed.h>", "private", "", "public" ] }, + { include: [ "<__type_traits/is_signed_integer.h>", "private", "", "public" ] }, + { include: [ "<__type_traits/is_specialization.h>", "private", "", "public" ] }, + { include: [ "<__type_traits/is_standard_layout.h>", "private", "", "public" ] }, + { include: [ "<__type_traits/is_swappable.h>", "private", "", "public" ] }, + { include: [ "<__type_traits/is_trivial.h>", "private", "", "public" ] }, + { include: [ "<__type_traits/is_trivially_assignable.h>", "private", "", "public" ] }, + { include: [ "<__type_traits/is_trivially_constructible.h>", "private", "", "public" ] }, + { include: [ "<__type_traits/is_trivially_copyable.h>", "private", "", "public" ] }, + { include: [ "<__type_traits/is_trivially_destructible.h>", "private", "", "public" ] }, + { include: [ "<__type_traits/is_trivially_lexicographically_comparable.h>", "private", "", "public" ] }, + { include: [ "<__type_traits/is_trivially_relocatable.h>", "private", "", "public" ] }, + { include: [ "<__type_traits/is_unbounded_array.h>", "private", "", "public" ] }, + { include: [ "<__type_traits/is_union.h>", "private", "", "public" ] }, + { include: [ "<__type_traits/is_unsigned.h>", "private", "", "public" ] }, + { include: [ "<__type_traits/is_unsigned_integer.h>", "private", "", "public" ] }, + { include: [ "<__type_traits/is_valid_expansion.h>", "private", "", "public" ] }, + { include: [ "<__type_traits/is_void.h>", "private", "", "public" ] }, + { include: [ "<__type_traits/is_volatile.h>", "private", "", "public" ] }, + { include: [ "<__type_traits/lazy.h>", "private", "", "public" ] }, + { include: [ "<__type_traits/make_32_64_or_128_bit.h>", "private", "", "public" ] }, + { include: [ "<__type_traits/make_const_lvalue_ref.h>", "private", "", "public" ] }, + { include: [ "<__type_traits/make_signed.h>", "private", "", "public" ] }, + { include: [ "<__type_traits/make_unsigned.h>", "private", "", "public" ] }, + { include: [ "<__type_traits/maybe_const.h>", "private", "", "public" ] }, + { include: [ "<__type_traits/nat.h>", "private", "", "public" ] }, + { include: [ "<__type_traits/negation.h>", "private", "", "public" ] }, + { include: [ "<__type_traits/noexcept_move_assign_container.h>", "private", "", "public" ] }, + { include: [ "<__type_traits/promote.h>", "private", "", "public" ] }, + { include: [ "<__type_traits/rank.h>", "private", "", "public" ] }, + { include: [ "<__type_traits/remove_all_extents.h>", "private", "", "public" ] }, + { include: [ "<__type_traits/remove_const.h>", "private", "", "public" ] }, + { include: [ "<__type_traits/remove_const_ref.h>", "private", "", "public" ] }, + { include: [ "<__type_traits/remove_cv.h>", "private", "", "public" ] }, + { include: [ "<__type_traits/remove_cvref.h>", "private", "", "public" ] }, + { include: [ "<__type_traits/remove_extent.h>", "private", "", "public" ] }, + { include: [ "<__type_traits/remove_pointer.h>", "private", "", "public" ] }, + { include: [ "<__type_traits/remove_reference.h>", "private", "", "public" ] }, + { include: [ "<__type_traits/remove_volatile.h>", "private", "", "public" ] }, + { include: [ "<__type_traits/result_of.h>", "private", "", "public" ] }, + { include: [ "<__type_traits/strip_signature.h>", "private", "", "public" ] }, + { include: [ "<__type_traits/type_identity.h>", "private", "", "public" ] }, + { include: [ "<__type_traits/type_list.h>", "private", "", "public" ] }, + { include: [ "<__type_traits/underlying_type.h>", "private", "", "public" ] }, + { include: [ "<__type_traits/unwrap_ref.h>", "private", "", "public" ] }, + { include: [ "<__type_traits/void_t.h>", "private", "", "public" ] }, + { include: [ "<__utility/as_const.h>", "private", "", "public" ] }, + { include: [ "<__utility/as_lvalue.h>", "private", "", "public" ] }, + { include: [ "<__utility/auto_cast.h>", "private", "", "public" ] }, + { include: [ "<__utility/cmp.h>", "private", "", "public" ] }, + { include: [ "<__utility/convert_to_integral.h>", "private", "", "public" ] }, + { include: [ "<__utility/declval.h>", "private", "", "public" ] }, + { include: [ "<__utility/empty.h>", "private", "", "public" ] }, + { include: [ "<__utility/exception_guard.h>", "private", "", "public" ] }, + { include: [ "<__utility/exchange.h>", "private", "", "public" ] }, + { include: [ "<__utility/forward.h>", "private", "", "public" ] }, + { include: [ "<__utility/forward_like.h>", "private", "", "public" ] }, + { include: [ "<__utility/in_place.h>", "private", "", "public" ] }, + { include: [ "<__utility/integer_sequence.h>", "private", "", "public" ] }, + { include: [ "<__utility/is_pointer_in_range.h>", "private", "", "public" ] }, + { include: [ "<__utility/move.h>", "private", "", "public" ] }, + { include: [ "<__utility/no_destroy.h>", "private", "", "public" ] }, + { include: [ "<__utility/pair.h>", "private", "", "public" ] }, + { include: [ "<__utility/piecewise_construct.h>", "private", "", "public" ] }, + { include: [ "<__utility/priority_tag.h>", "private", "", "public" ] }, + { include: [ "<__utility/rel_ops.h>", "private", "", "public" ] }, + { include: [ "<__utility/small_buffer.h>", "private", "", "public" ] }, + { include: [ "<__utility/swap.h>", "private", "", "public" ] }, + { include: [ "<__utility/to_underlying.h>", "private", "", "public" ] }, + { include: [ "<__utility/unreachable.h>", "private", "", "public" ] }, + { include: [ "<__variant/monostate.h>", "private", "", "public" ] }, +] diff --git a/libcxx/include/module.modulemap b/libcxx/include/module.modulemap index 70dac2f19846..8bc94d71391e 100644 --- a/libcxx/include/module.modulemap +++ b/libcxx/include/module.modulemap @@ -1066,7 +1066,11 @@ module std_private_atomic_atomic_flag [system] { } module std_private_atomic_atomic_init [system] { header "__atomic/atomic_init.h" } module std_private_atomic_atomic_lock_free [system] { header "__atomic/atomic_lock_free.h" } -module std_private_atomic_atomic_sync [system] { header "__atomic/atomic_sync.h" } +module std_private_atomic_atomic_ref [system] { header "__atomic/atomic_ref.h" } +module std_private_atomic_atomic_sync [system] { + header "__atomic/atomic_sync.h" + export std_private_atomic_to_gcc_order +} module std_private_atomic_check_memory_order [system] { header "__atomic/check_memory_order.h" } module std_private_atomic_contention_t [system] { header "__atomic/contention_t.h" } module std_private_atomic_cxx_atomic_impl [system] { header "__atomic/cxx_atomic_impl.h" } @@ -1074,6 +1078,10 @@ module std_private_atomic_fence [system] { header "__atomic/fence. module std_private_atomic_is_always_lock_free [system] { header "__atomic/is_always_lock_free.h" } module std_private_atomic_kill_dependency [system] { header "__atomic/kill_dependency.h" } module std_private_atomic_memory_order [system] { header "__atomic/memory_order.h" } +module std_private_atomic_to_gcc_order [system] { + header "__atomic/to_gcc_order.h" + export std_private_atomic_memory_order +} module std_private_bit_bit_cast [system] { header "__bit/bit_cast.h" } module std_private_bit_bit_ceil [system] { header "__bit/bit_ceil.h" } diff --git a/libcxx/modules/std/atomic.inc b/libcxx/modules/std/atomic.inc index d77d7a5bb0fb..e8cf90d01258 100644 --- a/libcxx/modules/std/atomic.inc +++ b/libcxx/modules/std/atomic.inc @@ -22,7 +22,7 @@ export namespace std { // [atomics.ref.generic], class template atomic_ref // [atomics.ref.pointer], partial specialization for pointers - // using std::atomic_ref _LIBCPP_USING_IF_EXISTS; + using std::atomic_ref _LIBCPP_USING_IF_EXISTS; // [atomics.types.generic], class template atomic using std::atomic _LIBCPP_USING_IF_EXISTS; diff --git a/libcxx/test/libcxx/atomics/atomics.ref/assert.compare_exchange_strong.pass.cpp b/libcxx/test/libcxx/atomics/atomics.ref/assert.compare_exchange_strong.pass.cpp new file mode 100644 index 000000000000..066ed1191dd0 --- /dev/null +++ b/libcxx/test/libcxx/atomics/atomics.ref/assert.compare_exchange_strong.pass.cpp @@ -0,0 +1,58 @@ +// +// 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 +// +//===----------------------------------------------------------------------===// + +// REQUIRES: has-unix-headers +// UNSUPPORTED: c++03, c++11, c++14, c++17 +// UNSUPPORTED: libcpp-hardening-mode=none || libcpp-hardening-mode=fast +// XFAIL: libcpp-hardening-mode=debug && availability-verbose_abort-missing +// ADDITIONAL_COMPILE_FLAGS: -Wno-user-defined-warnings + +// + +// bool compare_exchange_strong(T& expected, T desired, memory_order success, memory_order failure) const noexcept; +// +// Preconditions: failure is memory_order::relaxed, memory_order::consume, memory_order::acquire, or memory_order::seq_cst. + +#include + +#include "atomic_helpers.h" +#include "check_assertion.h" + +template +struct TestCompareExchangeStrongInvalidMemoryOrder { + void operator()() const { + { // no assertion should trigger here + T x(T(1)); + std::atomic_ref const a(x); + T t(T(2)); + a.compare_exchange_strong(t, T(3), std::memory_order_relaxed, std::memory_order_relaxed); + } + + TEST_LIBCPP_ASSERT_FAILURE( + ([] { + T x(T(1)); + std::atomic_ref const a(x); + T t(T(2)); + a.compare_exchange_strong(t, T(3), std::memory_order_relaxed, std::memory_order_release); + }()), + "atomic_ref: failure memory order argument to strong atomic compare-and-exchange operation is invalid"); + + TEST_LIBCPP_ASSERT_FAILURE( + ([] { + T x(T(1)); + std::atomic_ref const a(x); + T t(T(2)); + a.compare_exchange_strong(t, T(3), std::memory_order_relaxed, std::memory_order_acq_rel); + }()), + "atomic_ref: failure memory order argument to strong atomic compare-and-exchange operation is invalid"); + } +}; + +int main(int, char**) { + TestEachAtomicType()(); + return 0; +} diff --git a/libcxx/test/libcxx/atomics/atomics.ref/assert.compare_exchange_weak.pass.cpp b/libcxx/test/libcxx/atomics/atomics.ref/assert.compare_exchange_weak.pass.cpp new file mode 100644 index 000000000000..e83a143df3f0 --- /dev/null +++ b/libcxx/test/libcxx/atomics/atomics.ref/assert.compare_exchange_weak.pass.cpp @@ -0,0 +1,58 @@ +// +// 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 +// +//===----------------------------------------------------------------------===// + +// REQUIRES: has-unix-headers +// UNSUPPORTED: c++03, c++11, c++14, c++17 +// UNSUPPORTED: libcpp-hardening-mode=none || libcpp-hardening-mode=fast +// XFAIL: libcpp-hardening-mode=debug && availability-verbose_abort-missing +// ADDITIONAL_COMPILE_FLAGS: -Wno-user-defined-warnings + +// + +// bool compare_exchange_weak(T& expected, T desired, memory_order success, memory_order failure) const noexcept; +// +// Preconditions: failure is memory_order::relaxed, memory_order::consume, memory_order::acquire, or memory_order::seq_cst. + +#include + +#include "atomic_helpers.h" +#include "check_assertion.h" + +template +struct TestCompareExchangeWeakInvalidMemoryOrder { + void operator()() const { + { // no assertion should trigger here + T x(T(1)); + std::atomic_ref const a(x); + T t(T(2)); + a.compare_exchange_weak(t, T(3), std::memory_order_relaxed, std::memory_order_relaxed); + } + + TEST_LIBCPP_ASSERT_FAILURE( + ([] { + T x(T(1)); + std::atomic_ref const a(x); + T t(T(2)); + a.compare_exchange_weak(t, T(3), std::memory_order_relaxed, std::memory_order_release); + }()), + "atomic_ref: failure memory order argument to weak atomic compare-and-exchange operation is invalid"); + + TEST_LIBCPP_ASSERT_FAILURE( + ([] { + T x(T(1)); + std::atomic_ref const a(x); + T t(T(2)); + a.compare_exchange_weak(t, T(3), std::memory_order_relaxed, std::memory_order_acq_rel); + }()), + "atomic_ref: failure memory order argument to weak atomic compare-and-exchange operation is invalid"); + } +}; + +int main(int, char**) { + TestEachAtomicType()(); + return 0; +} diff --git a/libcxx/test/libcxx/atomics/atomics.ref/assert.ctor.pass.cpp b/libcxx/test/libcxx/atomics/atomics.ref/assert.ctor.pass.cpp new file mode 100644 index 000000000000..ef3705d1db27 --- /dev/null +++ b/libcxx/test/libcxx/atomics/atomics.ref/assert.ctor.pass.cpp @@ -0,0 +1,40 @@ +// +// 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 +// +//===----------------------------------------------------------------------===// + +// REQUIRES: has-unix-headers +// UNSUPPORTED: c++03, c++11, c++14, c++17 +// UNSUPPORTED: libcpp-hardening-mode=none || libcpp-hardening-mode=fast +// XFAIL: libcpp-hardening-mode=debug && availability-verbose_abort-missing + +// + +// atomic_ref(T& obj); +// +// Preconditions: The referenced object is aligned to required_alignment. + +#include +#include + +#include "check_assertion.h" + +int main(int, char**) { + { // no assertion should trigger here + alignas(float) std::byte c[sizeof(float)]; + float* f = new (c) float(3.14f); + [[maybe_unused]] std::atomic_ref r(*f); + } + + TEST_LIBCPP_ASSERT_FAILURE( + ([] { + alignas(float) std::byte c[2 * sizeof(float)]; // intentionally larger + float* f = new (c + 1) float(3.14f); // intentionally misaligned + [[maybe_unused]] std::atomic_ref r(*f); + }()), + "atomic_ref ctor: referenced object must be aligned to required_alignment"); + + return 0; +} diff --git a/libcxx/test/libcxx/atomics/atomics.ref/assert.load.pass.cpp b/libcxx/test/libcxx/atomics/atomics.ref/assert.load.pass.cpp new file mode 100644 index 000000000000..bc92b3dc3622 --- /dev/null +++ b/libcxx/test/libcxx/atomics/atomics.ref/assert.load.pass.cpp @@ -0,0 +1,55 @@ +// +// 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 +// +//===----------------------------------------------------------------------===// + +// REQUIRES: has-unix-headers +// UNSUPPORTED: c++03, c++11, c++14, c++17 +// UNSUPPORTED: libcpp-hardening-mode=none || libcpp-hardening-mode=fast +// XFAIL: libcpp-hardening-mode=debug && availability-verbose_abort-missing +// ADDITIONAL_COMPILE_FLAGS: -Wno-user-defined-warnings + +// + +// T load(memory_order order = memory_order::seq_cst) const noexcept; +// +// Preconditions: order is memory_order::relaxed, memory_order::consume, memory_order::acquire, or memory_order::seq_cst. + +#include + +#include "atomic_helpers.h" +#include "check_assertion.h" + +template +struct TestLoadInvalidMemoryOrder { + void operator()() const { + { // no assertion should trigger here + T x(T(1)); + std::atomic_ref const a(x); + (void)a.load(std::memory_order_relaxed); + } + + TEST_LIBCPP_ASSERT_FAILURE( + ([] { + T x(T(1)); + std::atomic_ref const a(x); + (void)a.load(std::memory_order_release); + }()), + "atomic_ref: memory order argument to atomic load operation is invalid"); + + TEST_LIBCPP_ASSERT_FAILURE( + ([] { + T x(T(1)); + std::atomic_ref const a(x); + (void)a.load(std::memory_order_acq_rel); + }()), + "atomic_ref: memory order argument to atomic load operation is invalid"); + } +}; + +int main(int, char**) { + TestEachAtomicType()(); + return 0; +} diff --git a/libcxx/test/libcxx/atomics/atomics.ref/assert.store.pass.cpp b/libcxx/test/libcxx/atomics/atomics.ref/assert.store.pass.cpp new file mode 100644 index 000000000000..ab0d4a220c94 --- /dev/null +++ b/libcxx/test/libcxx/atomics/atomics.ref/assert.store.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 +// +//===----------------------------------------------------------------------===// + +// REQUIRES: has-unix-headers +// UNSUPPORTED: c++03, c++11, c++14, c++17 +// UNSUPPORTED: libcpp-hardening-mode=none || libcpp-hardening-mode=fast +// XFAIL: libcpp-hardening-mode=debug && availability-verbose_abort-missing +// ADDITIONAL_COMPILE_FLAGS: -Wno-user-defined-warnings + +// + +// void store(T desired, memory_order order = memory_order::seq_cst) const noexcept; +// +// Preconditions: order is memory_order::relaxed, memory_order::release, or memory_order::seq_cst. + +#include + +#include "atomic_helpers.h" +#include "check_assertion.h" + +template +struct TestStoreInvalidMemoryOrder { + void operator()() const { + { // no assertion should trigger here + T x(T(1)); + std::atomic_ref const a(x); + a.store(T(2), std::memory_order_relaxed); + } + + TEST_LIBCPP_ASSERT_FAILURE( + ([] { + T x(T(1)); + std::atomic_ref const a(x); + a.store(T(2), std::memory_order_consume); + }()), + "atomic_ref: memory order argument to atomic store operation is invalid"); + + TEST_LIBCPP_ASSERT_FAILURE( + ([] { + T x(T(1)); + std::atomic_ref const a(x); + a.store(T(2), std::memory_order_acquire); + }()), + "atomic_ref: memory order argument to atomic store operation is invalid"); + + TEST_LIBCPP_ASSERT_FAILURE( + ([] { + T x(T(1)); + std::atomic_ref const a(x); + a.store(T(2), std::memory_order_acq_rel); + }()), + "atomic_ref: memory order argument to atomic store operation is invalid"); + } +}; + +int main(int, char**) { + TestEachAtomicType()(); + return 0; +} diff --git a/libcxx/test/libcxx/atomics/atomics.ref/assert.wait.pass.cpp b/libcxx/test/libcxx/atomics/atomics.ref/assert.wait.pass.cpp new file mode 100644 index 000000000000..dcec2fb62854 --- /dev/null +++ b/libcxx/test/libcxx/atomics/atomics.ref/assert.wait.pass.cpp @@ -0,0 +1,55 @@ +// +// 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 +// +//===----------------------------------------------------------------------===// + +// REQUIRES: has-unix-headers +// UNSUPPORTED: c++03, c++11, c++14, c++17 +// UNSUPPORTED: libcpp-hardening-mode=none || libcpp-hardening-mode=fast +// XFAIL: libcpp-hardening-mode=debug && availability-verbose_abort-missing +// ADDITIONAL_COMPILE_FLAGS: -Wno-user-defined-warnings + +// + +// void wait(T old, memory_order order = memory_order::seq_cst) const noexcept; +// +// Preconditions: order is memory_order::relaxed, memory_order::consume, memory_order::acquire, or memory_order::seq_cst. + +#include + +#include "atomic_helpers.h" +#include "check_assertion.h" + +template +struct TestWaitInvalidMemoryOrder { + void operator()() const { + { // no assertion should trigger here + T x(T(1)); + std::atomic_ref const a(x); + a.wait(T(2), std::memory_order_relaxed); + } + + TEST_LIBCPP_ASSERT_FAILURE( + ([] { + T x(T(1)); + std::atomic_ref const a(x); + a.wait(T(2), std::memory_order_release); + }()), + "atomic_ref: memory order argument to atomic wait operation is invalid"); + + TEST_LIBCPP_ASSERT_FAILURE( + ([] { + T x(T(1)); + std::atomic_ref const a(x); + a.wait(T(2), std::memory_order_acq_rel); + }()), + "atomic_ref: memory order argument to atomic wait operation is invalid"); + } +}; + +int main(int, char**) { + TestEachAtomicType()(); + return 0; +} diff --git a/libcxx/test/std/atomics/atomics.ref/assign.pass.cpp b/libcxx/test/std/atomics/atomics.ref/assign.pass.cpp new file mode 100644 index 000000000000..3887211752c6 --- /dev/null +++ b/libcxx/test/std/atomics/atomics.ref/assign.pass.cpp @@ -0,0 +1,50 @@ +// +// 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 +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14, c++17 +// XFAIL: !has-64-bit-atomics +// XFAIL: !has-1024-bit-atomics + +// T operator=(T) const noexcept; + +#include +#include +#include + +#include "atomic_helpers.h" +#include "test_helper.h" +#include "test_macros.h" + +template +struct TestAssign { + void operator()() const { + { + T x(T(1)); + std::atomic_ref const a(x); + + std::same_as decltype(auto) y = (a = T(2)); + assert(y == T(2)); + assert(x == T(2)); + + ASSERT_NOEXCEPT(a = T(0)); + static_assert(std::is_nothrow_assignable_v, T>); + + static_assert(!std::is_copy_assignable_v>); + } + + { + auto assign = [](std::atomic_ref const& y, T, T new_val) { y = new_val; }; + auto load = [](std::atomic_ref const& y) { return y.load(); }; + test_seq_cst(assign, load); + } + } +}; + +int main(int, char**) { + TestEachAtomicType()(); + return 0; +} diff --git a/libcxx/test/std/atomics/atomics.ref/bitwise_and_assign.pass.cpp b/libcxx/test/std/atomics/atomics.ref/bitwise_and_assign.pass.cpp new file mode 100644 index 000000000000..2be1e9962880 --- /dev/null +++ b/libcxx/test/std/atomics/atomics.ref/bitwise_and_assign.pass.cpp @@ -0,0 +1,60 @@ +// +// 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 +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14, c++17 +// XFAIL: !has-64-bit-atomics + +// integral-type operator&=(integral-type) const noexcept; + +#include +#include +#include +#include + +#include "atomic_helpers.h" +#include "test_macros.h" + +template +concept has_bitwise_and_assign = requires { std::declval() &= std::declval(); }; + +template +struct TestDoesNotHaveBitwiseAndAssign { + void operator()() const { static_assert(!has_bitwise_and_assign>); } +}; + +template +struct TestBitwiseAndAssign { + void operator()() const { + static_assert(std::is_integral_v); + + T x(T(1)); + std::atomic_ref const a(x); + + std::same_as decltype(auto) y = (a &= T(1)); + assert(y == T(1)); + assert(x == T(1)); + ASSERT_NOEXCEPT(a &= T(0)); + + y = (a &= T(2)); + assert(y == T(0)); + assert(x == T(0)); + } +}; + +int main(int, char**) { + TestEachIntegralType()(); + + TestEachFloatingPointType()(); + + TestEachPointerType()(); + + TestDoesNotHaveBitwiseAndAssign()(); + TestDoesNotHaveBitwiseAndAssign()(); + TestDoesNotHaveBitwiseAndAssign()(); + + return 0; +} diff --git a/libcxx/test/std/atomics/atomics.ref/bitwise_or_assign.pass.cpp b/libcxx/test/std/atomics/atomics.ref/bitwise_or_assign.pass.cpp new file mode 100644 index 000000000000..5c22c8a2b2b6 --- /dev/null +++ b/libcxx/test/std/atomics/atomics.ref/bitwise_or_assign.pass.cpp @@ -0,0 +1,56 @@ +// +// 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 +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14, c++17 +// XFAIL: !has-64-bit-atomics + +// integral-type operator|=(integral-type) const noexcept; + +#include +#include +#include +#include + +#include "atomic_helpers.h" +#include "test_macros.h" + +template +concept has_bitwise_or_assign = requires { std::declval() |= std::declval(); }; + +template < typename T> +struct TestDoesNotHaveBitwiseOrAssign { + void operator()() const { static_assert(!has_bitwise_or_assign>); } +}; + +template +struct TestBitwiseOrAssign { + void operator()() const { + static_assert(std::is_integral_v); + + T x(T(1)); + std::atomic_ref const a(x); + + std::same_as decltype(auto) y = (a |= T(2)); + assert(y == T(3)); + assert(x == T(3)); + ASSERT_NOEXCEPT(a |= T(0)); + } +}; + +int main(int, char**) { + TestEachIntegralType()(); + + TestEachFloatingPointType()(); + + TestEachPointerType()(); + + TestDoesNotHaveBitwiseOrAssign()(); + TestDoesNotHaveBitwiseOrAssign()(); + TestDoesNotHaveBitwiseOrAssign()(); + + return 0; +} diff --git a/libcxx/test/std/atomics/atomics.ref/bitwise_xor_assign.pass.cpp b/libcxx/test/std/atomics/atomics.ref/bitwise_xor_assign.pass.cpp new file mode 100644 index 000000000000..4dc4fd307f58 --- /dev/null +++ b/libcxx/test/std/atomics/atomics.ref/bitwise_xor_assign.pass.cpp @@ -0,0 +1,56 @@ +// +// 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 +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14, c++17 +// XFAIL: !has-64-bit-atomics + +// integral-type operator|=(integral-type) const noexcept; + +#include +#include +#include +#include + +#include "atomic_helpers.h" +#include "test_macros.h" + +template +concept has_bitwise_xor_assign = requires { std::declval() ^= std::declval(); }; + +template +struct TestDoesNotHaveBitwiseXorAssign { + void operator()() const { static_assert(!has_bitwise_xor_assign>); } +}; + +template +struct TestBitwiseXorAssign { + void operator()() const { + static_assert(std::is_integral_v); + + T x(T(1)); + std::atomic_ref const a(x); + + std::same_as decltype(auto) y = (a ^= T(2)); + assert(y == T(3)); + assert(x == T(3)); + ASSERT_NOEXCEPT(a ^= T(0)); + } +}; + +int main(int, char**) { + TestEachIntegralType()(); + + TestEachFloatingPointType()(); + + TestEachPointerType()(); + + TestDoesNotHaveBitwiseXorAssign()(); + TestDoesNotHaveBitwiseXorAssign()(); + TestDoesNotHaveBitwiseXorAssign()(); + + return 0; +} diff --git a/libcxx/test/std/atomics/atomics.ref/compare_exchange_strong.pass.cpp b/libcxx/test/std/atomics/atomics.ref/compare_exchange_strong.pass.cpp new file mode 100644 index 000000000000..72b2f444c476 --- /dev/null +++ b/libcxx/test/std/atomics/atomics.ref/compare_exchange_strong.pass.cpp @@ -0,0 +1,221 @@ +// +// 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 +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14, c++17 +// XFAIL: !has-64-bit-atomics +// XFAIL: !has-1024-bit-atomics + +// bool compare_exchange_strong(T&, T, memory_order, memory_order) const noexcept; +// bool compare_exchange_strong(T&, T, memory_order = memory_order::seq_cst) const noexcept; + +#include +#include +#include +#include + +#include "atomic_helpers.h" +#include "test_helper.h" +#include "test_macros.h" + +template +struct TestCompareExchangeStrong { + void operator()() const { + { + T x(T(1)); + std::atomic_ref const a(x); + + T t(T(1)); + std::same_as decltype(auto) y = a.compare_exchange_strong(t, T(2)); + assert(y == true); + assert(a == T(2)); + assert(t == T(1)); + y = a.compare_exchange_strong(t, T(3)); + assert(y == false); + assert(a == T(2)); + assert(t == T(2)); + + ASSERT_NOEXCEPT(a.compare_exchange_strong(t, T(2))); + } + { + T x(T(1)); + std::atomic_ref const a(x); + + T t(T(1)); + std::same_as decltype(auto) y = a.compare_exchange_strong(t, T(2), std::memory_order_seq_cst); + assert(y == true); + assert(a == T(2)); + assert(t == T(1)); + y = a.compare_exchange_strong(t, T(3), std::memory_order_seq_cst); + assert(y == false); + assert(a == T(2)); + assert(t == T(2)); + + ASSERT_NOEXCEPT(a.compare_exchange_strong(t, T(2), std::memory_order_seq_cst)); + } + { + T x(T(1)); + std::atomic_ref const a(x); + + T t(T(1)); + std::same_as decltype(auto) y = + a.compare_exchange_strong(t, T(2), std::memory_order_release, std::memory_order_relaxed); + assert(y == true); + assert(a == T(2)); + assert(t == T(1)); + y = a.compare_exchange_strong(t, T(3), std::memory_order_release, std::memory_order_relaxed); + assert(y == false); + assert(a == T(2)); + assert(t == T(2)); + + ASSERT_NOEXCEPT(a.compare_exchange_strong(t, T(2), std::memory_order_release, std::memory_order_relaxed)); + } + + // success memory_order::release + { + auto store = [](std::atomic_ref const& x, T old_val, T new_val) { + auto r = x.compare_exchange_strong(old_val, new_val, std::memory_order::release, std::memory_order::relaxed); + assert(r); + }; + + auto load = [](std::atomic_ref const& x) { return x.load(std::memory_order::acquire); }; + test_acquire_release(store, load); + + auto store_one_arg = [](std::atomic_ref const& x, T old_val, T new_val) { + auto r = x.compare_exchange_strong(old_val, new_val, std::memory_order::release); + assert(r); + }; + test_acquire_release(store_one_arg, load); + } + + // success memory_order::acquire + { + auto store = [](std::atomic_ref const& x, T, T new_val) { x.store(new_val, std::memory_order::release); }; + + auto load = [](std::atomic_ref const& x) { + auto val = x.load(std::memory_order::relaxed); + while (!x.compare_exchange_strong(val, val, std::memory_order::acquire, std::memory_order::relaxed)) { + } + return val; + }; + test_acquire_release(store, load); + + auto load_one_arg = [](std::atomic_ref const& x) { + auto val = x.load(std::memory_order::relaxed); + while (!x.compare_exchange_strong(val, val, std::memory_order::acquire)) { + } + return val; + }; + test_acquire_release(store, load_one_arg); + } + + // success memory_order::acq_rel + { + auto store = [](std::atomic_ref const& x, T old_val, T new_val) { + auto r = x.compare_exchange_strong(old_val, new_val, std::memory_order::acq_rel, std::memory_order::relaxed); + assert(r); + }; + auto load = [](std::atomic_ref const& x) { + auto val = x.load(std::memory_order::relaxed); + while (!x.compare_exchange_strong(val, val, std::memory_order::acq_rel, std::memory_order::relaxed)) { + } + return val; + }; + test_acquire_release(store, load); + + auto store_one_arg = [](std::atomic_ref const& x, T old_val, T new_val) { + auto r = x.compare_exchange_strong(old_val, new_val, std::memory_order::acq_rel); + assert(r); + }; + auto load_one_arg = [](std::atomic_ref const& x) { + auto val = x.load(std::memory_order::relaxed); + while (!x.compare_exchange_strong(val, val, std::memory_order::acq_rel)) { + } + return val; + }; + test_acquire_release(store_one_arg, load_one_arg); + } + + // success memory_order::seq_cst + { + auto store = [](std::atomic_ref const& x, T old_val, T new_val) { + auto r = x.compare_exchange_strong(old_val, new_val, std::memory_order::seq_cst, std::memory_order::relaxed); + assert(r); + }; + auto load = [](std::atomic_ref const& x) { + auto val = x.load(std::memory_order::relaxed); + while (!x.compare_exchange_strong(val, val, std::memory_order::seq_cst, std::memory_order::relaxed)) { + } + return val; + }; + test_seq_cst(store, load); + + auto store_one_arg = [](std::atomic_ref const& x, T old_val, T new_val) { + auto r = x.compare_exchange_strong(old_val, new_val, std::memory_order::seq_cst); + assert(r); + }; + auto load_one_arg = [](std::atomic_ref const& x) { + auto val = x.load(std::memory_order::relaxed); + while (!x.compare_exchange_strong(val, val, std::memory_order::seq_cst)) { + } + return val; + }; + test_seq_cst(store_one_arg, load_one_arg); + } + + // failure memory_order::acquire + { + auto store = [](std::atomic_ref const& x, T, T new_val) { x.store(new_val, std::memory_order::release); }; + auto load = [](std::atomic_ref const& x) { + auto result = x.load(std::memory_order::relaxed); + T unexpected(T(255)); + bool r = + x.compare_exchange_strong(unexpected, unexpected, std::memory_order::relaxed, std::memory_order::acquire); + assert(!r); + return result; + }; + test_acquire_release(store, load); + + auto load_one_arg = [](std::atomic_ref const& x) { + auto result = x.load(std::memory_order::relaxed); + T unexpected(T(255)); + bool r = x.compare_exchange_strong(unexpected, unexpected, std::memory_order::acquire); + assert(!r); + return result; + }; + test_acquire_release(store, load_one_arg); + + // acq_rel replaced by acquire + auto load_one_arg_acq_rel = [](std::atomic_ref const& x) { + auto result = x.load(std::memory_order::relaxed); + T unexpected(T(255)); + bool r = x.compare_exchange_strong(unexpected, unexpected, std::memory_order::acq_rel); + assert(!r); + return result; + }; + test_acquire_release(store, load_one_arg_acq_rel); + } + + // failure memory_order::seq_cst + { + auto store = [](std::atomic_ref const& x, T, T new_val) { x.store(new_val, std::memory_order::seq_cst); }; + auto load = [](std::atomic_ref const& x) { + auto result = x.load(std::memory_order::relaxed); + T unexpected(T(255)); + bool r = + x.compare_exchange_strong(unexpected, unexpected, std::memory_order::relaxed, std::memory_order::seq_cst); + assert(!r); + return result; + }; + test_seq_cst(store, load); + } + } +}; + +int main(int, char**) { + TestEachAtomicType()(); + return 0; +} diff --git a/libcxx/test/std/atomics/atomics.ref/compare_exchange_weak.pass.cpp b/libcxx/test/std/atomics/atomics.ref/compare_exchange_weak.pass.cpp new file mode 100644 index 000000000000..5219a8e3714f --- /dev/null +++ b/libcxx/test/std/atomics/atomics.ref/compare_exchange_weak.pass.cpp @@ -0,0 +1,226 @@ +// +// 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 +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14, c++17 +// XFAIL: !has-64-bit-atomics +// XFAIL: !has-1024-bit-atomics + +// bool compare_exchange_weak(T&, T, memory_order, memory_order) const noexcept; +// bool compare_exchange_weak(T&, T, memory_order = memory_order::seq_cst) const noexcept; + +#include +#include +#include +#include + +#include "atomic_helpers.h" +#include "test_helper.h" +#include "test_macros.h" + +template +struct TestCompareExchangeWeak { + void operator()() const { + { + T x(T(1)); + std::atomic_ref const a(x); + + T t(T(1)); + std::same_as decltype(auto) y = a.compare_exchange_weak(t, T(2)); + assert(y == true); + assert(a == T(2)); + assert(t == T(1)); + y = a.compare_exchange_weak(t, T(3)); + assert(y == false); + assert(a == T(2)); + assert(t == T(2)); + + ASSERT_NOEXCEPT(a.compare_exchange_weak(t, T(2))); + } + { + T x(T(1)); + std::atomic_ref const a(x); + + T t(T(1)); + std::same_as decltype(auto) y = a.compare_exchange_weak(t, T(2), std::memory_order_seq_cst); + assert(y == true); + assert(a == T(2)); + assert(t == T(1)); + y = a.compare_exchange_weak(t, T(3), std::memory_order_seq_cst); + assert(y == false); + assert(a == T(2)); + assert(t == T(2)); + + ASSERT_NOEXCEPT(a.compare_exchange_weak(t, T(2), std::memory_order_seq_cst)); + } + { + T x(T(1)); + std::atomic_ref const a(x); + + T t(T(1)); + std::same_as decltype(auto) y = + a.compare_exchange_weak(t, T(2), std::memory_order_release, std::memory_order_relaxed); + assert(y == true); + assert(a == T(2)); + assert(t == T(1)); + y = a.compare_exchange_weak(t, T(3), std::memory_order_release, std::memory_order_relaxed); + assert(y == false); + assert(a == T(2)); + assert(t == T(2)); + + ASSERT_NOEXCEPT(a.compare_exchange_weak(t, T(2), std::memory_order_release, std::memory_order_relaxed)); + } + + // success memory_order::release + { + auto store = [](std::atomic_ref const& x, T old_val, T new_val) { + // could fail spuriously, so put it in a loop + while (!x.compare_exchange_weak(old_val, new_val, std::memory_order::release, std::memory_order::relaxed)) { + } + }; + + auto load = [](std::atomic_ref const& x) { return x.load(std::memory_order::acquire); }; + test_acquire_release(store, load); + + auto store_one_arg = [](std::atomic_ref const& x, T old_val, T new_val) { + // could fail spuriously, so put it in a loop + while (!x.compare_exchange_weak(old_val, new_val, std::memory_order::release)) { + } + }; + test_acquire_release(store_one_arg, load); + } + + // success memory_order::acquire + { + auto store = [](std::atomic_ref const& x, T, T new_val) { x.store(new_val, std::memory_order::release); }; + auto load = [](std::atomic_ref const& x) { + auto val = x.load(std::memory_order::relaxed); + while (!x.compare_exchange_weak(val, val, std::memory_order::acquire, std::memory_order::relaxed)) { + } + return val; + }; + test_acquire_release(store, load); + + auto load_one_arg = [](std::atomic_ref const& x) { + auto val = x.load(std::memory_order::relaxed); + while (!x.compare_exchange_weak(val, val, std::memory_order::acquire)) { + } + return val; + }; + test_acquire_release(store, load_one_arg); + } + + // success memory_order::acq_rel + { + auto store = [](std::atomic_ref const& x, T old_val, T new_val) { + // could fail spuriously, so put it in a loop + while (!x.compare_exchange_weak(old_val, new_val, std::memory_order::acq_rel, std::memory_order::relaxed)) { + } + }; + auto load = [](std::atomic_ref const& x) { + auto val = x.load(std::memory_order::relaxed); + while (!x.compare_exchange_weak(val, val, std::memory_order::acq_rel, std::memory_order::relaxed)) { + } + return val; + }; + test_acquire_release(store, load); + + auto store_one_arg = [](std::atomic_ref const& x, T old_val, T new_val) { + // could fail spuriously, so put it in a loop + while (!x.compare_exchange_weak(old_val, new_val, std::memory_order::acq_rel)) { + } + }; + auto load_one_arg = [](std::atomic_ref const& x) { + auto val = x.load(std::memory_order::relaxed); + while (!x.compare_exchange_weak(val, val, std::memory_order::acq_rel)) { + } + return val; + }; + test_acquire_release(store_one_arg, load_one_arg); + } + + // success memory_order::seq_cst + { + auto store = [](std::atomic_ref const& x, T old_val, T new_val) { + // could fail spuriously, so put it in a loop + while (!x.compare_exchange_weak(old_val, new_val, std::memory_order::seq_cst, std::memory_order::relaxed)) { + } + }; + auto load = [](std::atomic_ref const& x) { + auto val = x.load(std::memory_order::relaxed); + while (!x.compare_exchange_weak(val, val, std::memory_order::seq_cst, std::memory_order::relaxed)) { + } + return val; + }; + test_seq_cst(store, load); + + auto store_one_arg = [](std::atomic_ref const& x, T old_val, T new_val) { + // could fail spuriously, so put it in a loop + while (!x.compare_exchange_weak(old_val, new_val, std::memory_order::seq_cst)) { + } + }; + auto load_one_arg = [](std::atomic_ref const& x) { + auto val = x.load(std::memory_order::relaxed); + while (!x.compare_exchange_weak(val, val, std::memory_order::seq_cst)) { + } + return val; + }; + test_seq_cst(store_one_arg, load_one_arg); + } + + // failure memory_order::acquire + { + auto store = [](std::atomic_ref const& x, T, T new_val) { x.store(new_val, std::memory_order::release); }; + auto load = [](std::atomic_ref const& x) { + auto result = x.load(std::memory_order::relaxed); + T unexpected(T(255)); + bool r = + x.compare_exchange_weak(unexpected, unexpected, std::memory_order::relaxed, std::memory_order::acquire); + assert(!r); + return result; + }; + test_acquire_release(store, load); + + auto load_one_arg = [](std::atomic_ref const& x) { + auto result = x.load(std::memory_order::relaxed); + T unexpected(T(255)); + bool r = x.compare_exchange_weak(unexpected, unexpected, std::memory_order::acquire); + assert(!r); + return result; + }; + test_acquire_release(store, load_one_arg); + + // acq_rel replaced by acquire + auto load_one_arg_acq_rel = [](std::atomic_ref const& x) { + auto result = x.load(std::memory_order::relaxed); + T unexpected(T(255)); + bool r = x.compare_exchange_weak(unexpected, unexpected, std::memory_order::acq_rel); + assert(!r); + return result; + }; + test_acquire_release(store, load_one_arg_acq_rel); + } + + // failure memory_order::seq_cst + { + auto store = [](std::atomic_ref const& x, T, T new_val) { x.store(new_val, std::memory_order::seq_cst); }; + auto load = [](std::atomic_ref const& x) { + auto result = x.load(std::memory_order::relaxed); + T unexpected(T(255)); + bool r = + x.compare_exchange_weak(unexpected, unexpected, std::memory_order::relaxed, std::memory_order::seq_cst); + assert(!r); + return result; + }; + test_seq_cst(store, load); + } + } +}; + +int main(int, char**) { + TestEachAtomicType()(); + return 0; +} diff --git a/libcxx/test/std/atomics/atomics.ref/convert.pass.cpp b/libcxx/test/std/atomics/atomics.ref/convert.pass.cpp new file mode 100644 index 000000000000..2a58a5ea6ae2 --- /dev/null +++ b/libcxx/test/std/atomics/atomics.ref/convert.pass.cpp @@ -0,0 +1,45 @@ +// +// 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 +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14, c++17 +// XFAIL: !has-64-bit-atomics +// XFAIL: !has-1024-bit-atomics + +// operator T() const noexcept; + +#include +#include +#include + +#include "atomic_helpers.h" +#include "test_helper.h" +#include "test_macros.h" + +template +struct TestConvert { + void operator()() const { + T x(T(1)); + + T copy = x; + std::atomic_ref const a(copy); + + T converted = a; + assert(converted == x); + + ASSERT_NOEXCEPT(T(a)); + static_assert(std::is_nothrow_convertible_v, T>); + + auto store = [](std::atomic_ref const& y, T, T new_val) { y.store(new_val); }; + auto load = [](std::atomic_ref const& y) { return static_cast(y); }; + test_seq_cst(store, load); + } +}; + +int main(int, char**) { + TestEachAtomicType()(); + return 0; +} diff --git a/libcxx/test/std/atomics/atomics.ref/ctor.pass.cpp b/libcxx/test/std/atomics/atomics.ref/ctor.pass.cpp new file mode 100644 index 000000000000..d6c647406abf --- /dev/null +++ b/libcxx/test/std/atomics/atomics.ref/ctor.pass.cpp @@ -0,0 +1,37 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14, c++17 + +// + +// explicit atomic_ref(T&); + +#include +#include + +#include "atomic_helpers.h" +#include "test_macros.h" + +template +struct TestCtor { + void operator()() const { + // check that the constructor is explicit + static_assert(!std::is_convertible_v>); + static_assert(std::is_constructible_v, T&>); + + T x(T(0)); + std::atomic_ref a(x); + (void)a; + } +}; + +int main(int, char**) { + TestEachAtomicType()(); + return 0; +} diff --git a/libcxx/test/std/atomics/atomics.ref/deduction.pass.cpp b/libcxx/test/std/atomics/atomics.ref/deduction.pass.cpp new file mode 100644 index 000000000000..24a399ac4711 --- /dev/null +++ b/libcxx/test/std/atomics/atomics.ref/deduction.pass.cpp @@ -0,0 +1,33 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14, c++17 + +// + +// explicit atomic_ref(T&); + +#include +#include + +#include "atomic_helpers.h" +#include "test_macros.h" + +template +struct TestDeduction { + void operator()() const { + T x(T(0)); + std::atomic_ref a(x); + ASSERT_SAME_TYPE(decltype(a), std::atomic_ref); + } +}; + +int main(int, char**) { + TestEachAtomicType()(); + return 0; +} diff --git a/libcxx/test/std/atomics/atomics.ref/exchange.pass.cpp b/libcxx/test/std/atomics/atomics.ref/exchange.pass.cpp new file mode 100644 index 000000000000..cd998d46b7e8 --- /dev/null +++ b/libcxx/test/std/atomics/atomics.ref/exchange.pass.cpp @@ -0,0 +1,45 @@ +// +// 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 +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14, c++17 +// XFAIL: !has-64-bit-atomics +// XFAIL: !has-1024-bit-atomics + +// T exchange(T, memory_order = memory_order::seq_cst) const noexcept; + +#include +#include +#include +#include + +#include "atomic_helpers.h" +#include "test_macros.h" + +template +struct TestExchange { + void operator()() const { + T x(T(1)); + std::atomic_ref const a(x); + + { + std::same_as decltype(auto) y = a.exchange(T(2)); + assert(y == T(1)); + ASSERT_NOEXCEPT(a.exchange(T(2))); + } + + { + std::same_as decltype(auto) y = a.exchange(T(3), std::memory_order_seq_cst); + assert(y == T(2)); + ASSERT_NOEXCEPT(a.exchange(T(3), std::memory_order_seq_cst)); + } + } +}; + +int main(int, char**) { + TestEachAtomicType()(); + return 0; +} diff --git a/libcxx/test/std/atomics/atomics.ref/fetch_add.pass.cpp b/libcxx/test/std/atomics/atomics.ref/fetch_add.pass.cpp new file mode 100644 index 000000000000..908a6879bd06 --- /dev/null +++ b/libcxx/test/std/atomics/atomics.ref/fetch_add.pass.cpp @@ -0,0 +1,113 @@ +// +// 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 +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14, c++17 +// XFAIL: !has-64-bit-atomics + +// integral-type fetch_add(integral-type, memory_order = memory_order::seq_cst) const noexcept; +// floating-point-type fetch_add(floating-point-type, memory_order = memory_order::seq_cst) const noexcept; +// T* fetch_add(difference_type, memory_order = memory_order::seq_cst) const noexcept; + +#include +#include +#include +#include + +#include "atomic_helpers.h" +#include "test_helper.h" +#include "test_macros.h" + +template +concept has_fetch_add = requires { + std::declval().fetch_add(std::declval()); + std::declval().fetch_add(std::declval(), std::declval()); +}; + +template +struct TestDoesNotHaveFetchAdd { + void operator()() const { static_assert(!has_fetch_add>); } +}; + +template +struct TestFetchAdd { + void operator()() const { + if constexpr (std::is_arithmetic_v) { + T x(T(1)); + std::atomic_ref const a(x); + + { + std::same_as decltype(auto) y = a.fetch_add(T(2)); + assert(y == T(1)); + assert(x == T(3)); + ASSERT_NOEXCEPT(a.fetch_add(T(0))); + } + + { + std::same_as decltype(auto) y = a.fetch_add(T(4), std::memory_order_relaxed); + assert(y == T(3)); + assert(x == T(7)); + ASSERT_NOEXCEPT(a.fetch_add(T(0), std::memory_order_relaxed)); + } + } else if constexpr (std::is_pointer_v) { + using U = std::remove_pointer_t; + U t[9] = {}; + T p{&t[1]}; + std::atomic_ref const a(p); + + { + std::same_as decltype(auto) y = a.fetch_add(2); + assert(y == &t[1]); + assert(a == &t[3]); + ASSERT_NOEXCEPT(a.fetch_add(0)); + } + + { + std::same_as decltype(auto) y = a.fetch_add(4, std::memory_order_relaxed); + assert(y == &t[3]); + assert(a == &t[7]); + ASSERT_NOEXCEPT(a.fetch_add(0, std::memory_order_relaxed)); + } + } else { + static_assert(std::is_void_v); + } + + // memory_order::release + { + auto fetch_add = [](std::atomic_ref const& x, T old_val, T new_val) { + x.fetch_add(new_val - old_val, std::memory_order::release); + }; + auto load = [](std::atomic_ref const& x) { return x.load(std::memory_order::acquire); }; + test_acquire_release(fetch_add, load); + } + + // memory_order::seq_cst + { + auto fetch_add_no_arg = [](std::atomic_ref const& x, T old_val, T new_val) { x.fetch_add(new_val - old_val); }; + auto fetch_add_with_order = [](std::atomic_ref const& x, T old_val, T new_val) { + x.fetch_add(new_val - old_val, std::memory_order::seq_cst); + }; + auto load = [](std::atomic_ref const& x) { return x.load(); }; + test_seq_cst(fetch_add_no_arg, load); + test_seq_cst(fetch_add_with_order, load); + } + } +}; + +int main(int, char**) { + TestEachIntegralType()(); + + TestFetchAdd()(); + TestFetchAdd()(); + + TestEachPointerType()(); + + TestDoesNotHaveFetchAdd()(); + TestDoesNotHaveFetchAdd()(); + TestDoesNotHaveFetchAdd()(); + + return 0; +} diff --git a/libcxx/test/std/atomics/atomics.ref/fetch_and.pass.cpp b/libcxx/test/std/atomics/atomics.ref/fetch_and.pass.cpp new file mode 100644 index 000000000000..8f0bec21fe72 --- /dev/null +++ b/libcxx/test/std/atomics/atomics.ref/fetch_and.pass.cpp @@ -0,0 +1,69 @@ +// +// 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 +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14, c++17 +// XFAIL: !has-64-bit-atomics + +// integral-type fetch_and(integral-type, memory_order = memory_order::seq_cst) const noexcept; + +#include +#include +#include +#include + +#include "atomic_helpers.h" +#include "test_macros.h" + +template +concept has_fetch_and = requires { + std::declval().fetch_and(std::declval()); + std::declval().fetch_and(std::declval(), std::declval()); +}; + +template +struct TestDoesNotHaveFetchAnd { + void operator()() const { static_assert(!has_fetch_and>); } +}; + +template +struct TestFetchAnd { + void operator()() const { + static_assert(std::is_integral_v); + + T x(T(1)); + std::atomic_ref const a(x); + + { + std::same_as decltype(auto) y = a.fetch_and(T(2)); + assert(y == T(1)); + assert(x == T(0)); + ASSERT_NOEXCEPT(a.fetch_and(T(0))); + } + + x = T(1); + + { + std::same_as decltype(auto) y = a.fetch_and(T(2), std::memory_order_relaxed); + assert(y == T(1)); + assert(x == T(0)); + ASSERT_NOEXCEPT(a.fetch_and(T(0), std::memory_order_relaxed)); + } + } +}; + +int main(int, char**) { + TestEachIntegralType()(); + + TestEachFloatingPointType()(); + + TestEachPointerType()(); + + TestDoesNotHaveFetchAnd()(); + TestDoesNotHaveFetchAnd()(); + TestDoesNotHaveFetchAnd()(); + return 0; +} diff --git a/libcxx/test/std/atomics/atomics.ref/fetch_or.pass.cpp b/libcxx/test/std/atomics/atomics.ref/fetch_or.pass.cpp new file mode 100644 index 000000000000..2045868fde42 --- /dev/null +++ b/libcxx/test/std/atomics/atomics.ref/fetch_or.pass.cpp @@ -0,0 +1,68 @@ +// +// 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 +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14, c++17 +// XFAIL: !has-64-bit-atomics + +// integral-type fetch_or(integral-type, memory_order = memory_order::seq_cst) const noexcept; + +#include +#include +#include +#include + +#include "atomic_helpers.h" +#include "test_macros.h" + +template +concept has_fetch_or = requires { + std::declval().fetch_or(std::declval()); + std::declval().fetch_or(std::declval(), std::declval()); +}; + +template +struct TestDoesNotHaveFetchOr { + void operator()() const { static_assert(!has_fetch_or>); } +}; + +template +struct TestFetchOr { + void operator()() const { + static_assert(std::is_integral_v); + + T x(T(1)); + std::atomic_ref const a(x); + + { + std::same_as decltype(auto) y = a.fetch_or(T(2)); + assert(y == T(1)); + assert(x == T(3)); + ASSERT_NOEXCEPT(a.fetch_or(T(0))); + } + + { + std::same_as decltype(auto) y = a.fetch_or(T(2), std::memory_order_relaxed); + assert(y == T(3)); + assert(x == T(3)); + ASSERT_NOEXCEPT(a.fetch_or(T(0), std::memory_order_relaxed)); + } + } +}; + +int main(int, char**) { + TestEachIntegralType()(); + + TestEachFloatingPointType()(); + + TestEachPointerType()(); + + TestDoesNotHaveFetchOr()(); + TestDoesNotHaveFetchOr()(); + TestDoesNotHaveFetchOr()(); + + return 0; +} diff --git a/libcxx/test/std/atomics/atomics.ref/fetch_sub.pass.cpp b/libcxx/test/std/atomics/atomics.ref/fetch_sub.pass.cpp new file mode 100644 index 000000000000..545604530ada --- /dev/null +++ b/libcxx/test/std/atomics/atomics.ref/fetch_sub.pass.cpp @@ -0,0 +1,113 @@ +// +// 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 +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14, c++17 +// XFAIL: !has-64-bit-atomics + +// integral-type fetch_sub(integral-type, memory_order = memory_order::seq_cst) const noexcept; +// floating-point-type fetch_sub(floating-point-type, memory_order = memory_order::seq_cst) const noexcept; +// T* fetch_sub(difference_type, memory_order = memory_order::seq_cst) const noexcept; + +#include +#include +#include +#include + +#include "atomic_helpers.h" +#include "test_helper.h" +#include "test_macros.h" + +template +concept has_fetch_sub = requires { + std::declval().fetch_sub(std::declval()); + std::declval().fetch_sub(std::declval(), std::declval()); +}; + +template +struct TestDoesNotHaveFetchSub { + void operator()() const { static_assert(!has_fetch_sub>); } +}; + +template +struct TestFetchSub { + void operator()() const { + if constexpr (std::is_arithmetic_v) { + T x(T(7)); + std::atomic_ref const a(x); + + { + std::same_as decltype(auto) y = a.fetch_sub(T(4)); + assert(y == T(7)); + assert(x == T(3)); + ASSERT_NOEXCEPT(a.fetch_sub(T(0))); + } + + { + std::same_as decltype(auto) y = a.fetch_sub(T(2), std::memory_order_relaxed); + assert(y == T(3)); + assert(x == T(1)); + ASSERT_NOEXCEPT(a.fetch_sub(T(0), std::memory_order_relaxed)); + } + } else if constexpr (std::is_pointer_v) { + using U = std::remove_pointer_t; + U t[9] = {}; + T p{&t[7]}; + std::atomic_ref const a(p); + + { + std::same_as decltype(auto) y = a.fetch_sub(4); + assert(y == &t[7]); + assert(a == &t[3]); + ASSERT_NOEXCEPT(a.fetch_sub(0)); + } + + { + std::same_as decltype(auto) y = a.fetch_sub(2, std::memory_order_relaxed); + assert(y == &t[3]); + assert(a == &t[1]); + ASSERT_NOEXCEPT(a.fetch_sub(0, std::memory_order_relaxed)); + } + } else { + static_assert(std::is_void_v); + } + + // memory_order::release + { + auto fetch_sub = [](std::atomic_ref const& x, T old_val, T new_val) { + x.fetch_sub(old_val - new_val, std::memory_order::release); + }; + auto load = [](std::atomic_ref const& x) { return x.load(std::memory_order::acquire); }; + test_acquire_release(fetch_sub, load); + } + + // memory_order::seq_cst + { + auto fetch_sub_no_arg = [](std::atomic_ref const& x, T old_val, T new_val) { x.fetch_sub(old_val - new_val); }; + auto fetch_sub_with_order = [](std::atomic_ref const& x, T old_val, T new_val) { + x.fetch_sub(old_val - new_val, std::memory_order::seq_cst); + }; + auto load = [](std::atomic_ref const& x) { return x.load(); }; + test_seq_cst(fetch_sub_no_arg, load); + test_seq_cst(fetch_sub_with_order, load); + } + } +}; + +int main(int, char**) { + TestEachIntegralType()(); + + TestFetchSub()(); + TestFetchSub()(); + + TestEachPointerType()(); + + TestDoesNotHaveFetchSub()(); + TestDoesNotHaveFetchSub()(); + TestDoesNotHaveFetchSub()(); + + return 0; +} diff --git a/libcxx/test/std/atomics/atomics.ref/fetch_xor.pass.cpp b/libcxx/test/std/atomics/atomics.ref/fetch_xor.pass.cpp new file mode 100644 index 000000000000..aade87f961f1 --- /dev/null +++ b/libcxx/test/std/atomics/atomics.ref/fetch_xor.pass.cpp @@ -0,0 +1,68 @@ +// +// 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 +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14, c++17 +// XFAIL: !has-64-bit-atomics + +// integral-type fetch_xor(integral-type, memory_order = memory_order::seq_cst) const noexcept; + +#include +#include +#include +#include + +#include "atomic_helpers.h" +#include "test_macros.h" + +template +concept has_fetch_xor = requires { + std::declval().fetch_xor(std::declval()); + std::declval().fetch_xor(std::declval(), std::declval()); +}; + +template +struct TestDoesNotHaveFetchXor { + void operator()() const { static_assert(!has_fetch_xor>); } +}; + +template +struct TestFetchXor { + void operator()() const { + static_assert(std::is_integral_v); + + T x(T(1)); + std::atomic_ref const a(x); + + { + std::same_as decltype(auto) y = a.fetch_xor(T(2)); + assert(y == T(1)); + assert(x == T(3)); + ASSERT_NOEXCEPT(a.fetch_xor(T(0))); + } + + { + std::same_as decltype(auto) y = a.fetch_xor(T(2), std::memory_order_relaxed); + assert(y == T(3)); + assert(x == T(1)); + ASSERT_NOEXCEPT(a.fetch_xor(T(0), std::memory_order_relaxed)); + } + } +}; + +int main(int, char**) { + TestEachIntegralType()(); + + TestEachFloatingPointType()(); + + TestEachPointerType()(); + + TestDoesNotHaveFetchXor()(); + TestDoesNotHaveFetchXor()(); + TestDoesNotHaveFetchXor()(); + + return 0; +} diff --git a/libcxx/test/std/atomics/atomics.ref/increment_decrement.pass.cpp b/libcxx/test/std/atomics/atomics.ref/increment_decrement.pass.cpp new file mode 100644 index 000000000000..c84c89b4d2b4 --- /dev/null +++ b/libcxx/test/std/atomics/atomics.ref/increment_decrement.pass.cpp @@ -0,0 +1,97 @@ +// +// 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 +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14, c++17 +// XFAIL: !has-64-bit-atomics + +// integral-type operator++(int) const noexcept; +// integral-type operator--(int) const noexcept; +// integral-type operator++() const noexcept; +// integral-type operator--() const noexcept; + +#include +#include +#include +#include + +#include "atomic_helpers.h" +#include "test_macros.h" + +template +concept has_pre_increment_operator = requires { ++std::declval(); }; + +template +concept has_post_increment_operator = requires { std::declval()++; }; + +template +concept has_pre_decrement_operator = requires { --std::declval(); }; + +template +concept has_post_decrement_operator = requires { std::declval()--; }; + +template +constexpr bool does_not_have_increment_nor_decrement_operators() { + return !has_pre_increment_operator && !has_pre_decrement_operator && !has_post_increment_operator && + !has_post_decrement_operator; +} + +template +struct TestDoesNotHaveIncrementDecrement { + void operator()() const { static_assert(does_not_have_increment_nor_decrement_operators()); } +}; + +template +struct TestIncrementDecrement { + void operator()() const { + static_assert(std::is_integral_v); + + T x(T(1)); + std::atomic_ref const a(x); + + { + std::same_as decltype(auto) y = ++a; + assert(y == T(2)); + assert(x == T(2)); + ASSERT_NOEXCEPT(++a); + } + + { + std::same_as decltype(auto) y = --a; + assert(y == T(1)); + assert(x == T(1)); + ASSERT_NOEXCEPT(--a); + } + + { + std::same_as decltype(auto) y = a++; + assert(y == T(1)); + assert(x == T(2)); + ASSERT_NOEXCEPT(a++); + } + + { + std::same_as decltype(auto) y = a--; + assert(y == T(2)); + assert(x == T(1)); + ASSERT_NOEXCEPT(a--); + } + } +}; + +int main(int, char**) { + TestEachIntegralType()(); + + TestEachFloatingPointType()(); + + TestEachPointerType()(); + + TestDoesNotHaveIncrementDecrement()(); + TestDoesNotHaveIncrementDecrement()(); + TestDoesNotHaveIncrementDecrement()(); + + return 0; +} diff --git a/libcxx/test/std/atomics/atomics.ref/is_always_lock_free.pass.cpp b/libcxx/test/std/atomics/atomics.ref/is_always_lock_free.pass.cpp new file mode 100644 index 000000000000..94f65e3b4b66 --- /dev/null +++ b/libcxx/test/std/atomics/atomics.ref/is_always_lock_free.pass.cpp @@ -0,0 +1,71 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14, c++17 + +// + +// static constexpr bool is_always_lock_free; +// bool is_lock_free() const noexcept; + +#include +#include +#include + +#include "test_macros.h" + +template +void check_always_lock_free(std::atomic_ref const a) { + std::same_as decltype(auto) is_always_lock_free = std::atomic_ref::is_always_lock_free; + if (is_always_lock_free) { + std::same_as decltype(auto) is_lock_free = a.is_lock_free(); + assert(is_lock_free); + } + ASSERT_NOEXCEPT(a.is_lock_free()); +} + +#define CHECK_ALWAYS_LOCK_FREE(T) \ + do { \ + typedef T type; \ + type obj{}; \ + check_always_lock_free(std::atomic_ref(obj)); \ + } while (0) + +void test() { + int i = 0; + check_always_lock_free(std::atomic_ref(i)); + + float f = 0.f; + check_always_lock_free(std::atomic_ref(f)); + + int* p = &i; + check_always_lock_free(std::atomic_ref(p)); + + CHECK_ALWAYS_LOCK_FREE(struct Empty{}); + CHECK_ALWAYS_LOCK_FREE(struct OneInt { int i; }); + CHECK_ALWAYS_LOCK_FREE(struct IntArr2 { int i[2]; }); + CHECK_ALWAYS_LOCK_FREE(struct FloatArr3 { float i[3]; }); + CHECK_ALWAYS_LOCK_FREE(struct LLIArr2 { long long int i[2]; }); + CHECK_ALWAYS_LOCK_FREE(struct LLIArr4 { long long int i[4]; }); + CHECK_ALWAYS_LOCK_FREE(struct LLIArr8 { long long int i[8]; }); + CHECK_ALWAYS_LOCK_FREE(struct LLIArr16 { long long int i[16]; }); + CHECK_ALWAYS_LOCK_FREE(struct Padding { + char c; /* padding */ + long long int i; + }); + CHECK_ALWAYS_LOCK_FREE(union IntFloat { + int i; + float f; + }); + CHECK_ALWAYS_LOCK_FREE(enum class CharEnumClass : char{foo}); +} + +int main(int, char**) { + test(); + return 0; +} diff --git a/libcxx/test/std/atomics/atomics.ref/load.pass.cpp b/libcxx/test/std/atomics/atomics.ref/load.pass.cpp new file mode 100644 index 000000000000..feed0fbaed84 --- /dev/null +++ b/libcxx/test/std/atomics/atomics.ref/load.pass.cpp @@ -0,0 +1,62 @@ +// +// 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 +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14, c++17 +// XFAIL: !has-64-bit-atomics +// XFAIL: !has-1024-bit-atomics + +// T load(memory_order = memory_order::seq_cst) const noexcept; + +#include +#include +#include +#include + +#include "atomic_helpers.h" +#include "test_helper.h" +#include "test_macros.h" + +template +struct TestLoad { + void operator()() const { + T x(T(1)); + std::atomic_ref const a(x); + + { + std::same_as decltype(auto) y = a.load(); + assert(y == T(1)); + ASSERT_NOEXCEPT(a.load()); + } + + { + std::same_as decltype(auto) y = a.load(std::memory_order_seq_cst); + assert(y == T(1)); + ASSERT_NOEXCEPT(a.load(std::memory_order_seq_cst)); + } + + // memory_order::seq_cst + { + auto store = [](std::atomic_ref const& y, T, T new_val) { y.store(new_val); }; + auto load_no_arg = [](std::atomic_ref const& y) { return y.load(); }; + auto load_with_order = [](std::atomic_ref const& y) { return y.load(std::memory_order::seq_cst); }; + test_seq_cst(store, load_no_arg); + test_seq_cst(store, load_with_order); + } + + // memory_order::release + { + auto store = [](std::atomic_ref const& y, T, T new_val) { y.store(new_val, std::memory_order::release); }; + auto load = [](std::atomic_ref const& y) { return y.load(std::memory_order::acquire); }; + test_acquire_release(store, load); + } + } +}; + +int main(int, char**) { + TestEachAtomicType()(); + return 0; +} diff --git a/libcxx/test/std/atomics/atomics.ref/member_types.pass.cpp b/libcxx/test/std/atomics/atomics.ref/member_types.pass.cpp new file mode 100644 index 000000000000..d4e2f0126d62 --- /dev/null +++ b/libcxx/test/std/atomics/atomics.ref/member_types.pass.cpp @@ -0,0 +1,132 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// +// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20 + +// + +// template +// struct atomic_ref +// { +// using value_type = T; +// using difference_type = value_type; // only for atomic_ref and +// // atomic_ref specializations +// using difference_type = std::ptrdiff_t; // only for atomic_ref specializations +// +// explicit atomic_ref(T&); +// atomic_ref(const atomic_ref&) noexcept; +// atomic_ref& operator=(const atomic_ref&) = delete; +// }; + +#include +#include + +#include "test_macros.h" + +template +concept has_difference_type = requires { typename T::difference_type; }; + +template +void check_member_types() { + if constexpr ((std::is_integral_v && !std::is_same_v) || std::is_floating_point_v) { + ASSERT_SAME_TYPE(typename std::atomic_ref::value_type, T); + ASSERT_SAME_TYPE(typename std::atomic_ref::difference_type, T); + } else if constexpr (std::is_pointer_v) { + ASSERT_SAME_TYPE(typename std::atomic_ref::value_type, T); + ASSERT_SAME_TYPE(typename std::atomic_ref::difference_type, std::ptrdiff_t); + } else { + ASSERT_SAME_TYPE(typename std::atomic_ref::value_type, T); + static_assert(!has_difference_type>); + } +} + +template +void test() { + // value_type and difference_type (except for primary template) + check_member_types(); + + static_assert(std::is_nothrow_copy_constructible_v>); + + static_assert(!std::is_copy_assignable_v>); + + // explicit constructor + static_assert(!std::is_convertible_v>); + static_assert(std::is_constructible_v, T&>); +} + +void testall() { + // Primary template + struct Empty {}; + test(); + struct Trivial { + int a; + float b; + }; + test(); + test(); + + // Partial specialization for pointer types + test(); + + // Specialization for integral types + // + character types + test(); + test(); + test(); + test(); + test(); + // + standard signed integer types + test(); + test(); + test(); + test(); + test(); + // + standard unsigned integer types + test(); + test(); + test(); + test(); + test(); + // + any other types needed by the typedefs in the header + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + + // Specialization for floating-point types + // + floating-point types + test(); + test(); + test(); + // + TODO extended floating-point types +} + +int main(int, char**) { return 0; } diff --git a/libcxx/test/std/atomics/atomics.ref/notify_all.pass.cpp b/libcxx/test/std/atomics/atomics.ref/notify_all.pass.cpp new file mode 100644 index 000000000000..382b19f8c1d7 --- /dev/null +++ b/libcxx/test/std/atomics/atomics.ref/notify_all.pass.cpp @@ -0,0 +1,78 @@ +// +// 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 +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14, c++17 +// UNSUPPORTED: no-threads +// XFAIL: availability-synchronization_library-missing +// XFAIL: !has-64-bit-atomics +// XFAIL: !has-1024-bit-atomics + +// void notify_all() const noexcept; + +#include +#include +#include +#include +#include + +#include "atomic_helpers.h" +#include "make_test_thread.h" +#include "test_macros.h" + +template +struct TestNotifyAll { + void operator()() const { + T x(T(1)); + std::atomic_ref const a(x); + + bool done = false; + std::atomic started_num = 0; + std::atomic wait_done_num = 0; + + constexpr auto number_of_threads = 8; + std::vector threads; + threads.reserve(number_of_threads); + + for (auto j = 0; j < number_of_threads; ++j) { + threads.push_back(support::make_test_thread([&a, &started_num, &done, &wait_done_num] { + started_num.fetch_add(1, std::memory_order::relaxed); + + a.wait(T(1)); + wait_done_num.fetch_add(1, std::memory_order::relaxed); + + // likely to fail if wait did not block + assert(done); + })); + } + + while (started_num.load(std::memory_order::relaxed) != number_of_threads) { + std::this_thread::yield(); + } + + std::this_thread::sleep_for(std::chrono::milliseconds(1)); + + done = true; + a.store(T(3)); + a.notify_all(); + + // notify_all should unblock all the threads so that the loop below won't stuck + while (wait_done_num.load(std::memory_order::relaxed) != number_of_threads) { + std::this_thread::yield(); + } + + for (auto& thread : threads) { + thread.join(); + } + + ASSERT_NOEXCEPT(a.notify_all()); + } +}; + +int main(int, char**) { + TestEachAtomicType()(); + return 0; +} diff --git a/libcxx/test/std/atomics/atomics.ref/notify_one.pass.cpp b/libcxx/test/std/atomics/atomics.ref/notify_one.pass.cpp new file mode 100644 index 000000000000..611e67417e4d --- /dev/null +++ b/libcxx/test/std/atomics/atomics.ref/notify_one.pass.cpp @@ -0,0 +1,46 @@ +// +// 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 +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14, c++17 +// UNSUPPORTED: no-threads +// XFAIL: availability-synchronization_library-missing +// XFAIL: !has-64-bit-atomics +// XFAIL: !has-1024-bit-atomics + +// void notify_one() const noexcept; + +#include +#include +#include +#include +#include + +#include "atomic_helpers.h" +#include "make_test_thread.h" +#include "test_macros.h" + +template +struct TestNotifyOne { + void operator()() const { + T x(T(1)); + std::atomic_ref const a(x); + + std::thread t = support::make_test_thread([&]() { + a.store(T(3)); + a.notify_one(); + }); + a.wait(T(1)); + assert(a.load() == T(3)); + t.join(); + ASSERT_NOEXCEPT(a.notify_one()); + } +}; + +int main(int, char**) { + TestEachAtomicType()(); + return 0; +} diff --git a/libcxx/test/std/atomics/atomics.ref/operator_minus_equals.pass.cpp b/libcxx/test/std/atomics/atomics.ref/operator_minus_equals.pass.cpp new file mode 100644 index 000000000000..571d626035fa --- /dev/null +++ b/libcxx/test/std/atomics/atomics.ref/operator_minus_equals.pass.cpp @@ -0,0 +1,79 @@ +// +// 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 +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14, c++17 +// XFAIL: !has-64-bit-atomics + +// integral-type operator-=(integral-type) const noexcept; +// floating-point-type operator-=(floating-point-type) const noexcept; +// T* operator-=(difference_type) const noexcept; + +#include +#include +#include +#include + +#include "atomic_helpers.h" +#include "test_helper.h" +#include "test_macros.h" + +template +concept has_operator_minus_equals = requires { std::declval() -= std::declval(); }; + +template +struct TestDoesNotHaveOperatorMinusEquals { + void operator()() const { static_assert(!has_operator_minus_equals>); } +}; + +template +struct TestOperatorMinusEquals { + void operator()() const { + if constexpr (std::is_arithmetic_v) { + T x(T(3)); + std::atomic_ref const a(x); + + std::same_as decltype(auto) y = (a -= T(2)); + assert(y == T(1)); + assert(x == T(1)); + ASSERT_NOEXCEPT(a -= T(0)); + } else if constexpr (std::is_pointer_v) { + using U = std::remove_pointer_t; + U t[9] = {}; + T p{&t[3]}; + std::atomic_ref const a(p); + + std::same_as decltype(auto) y = (a -= 2); + assert(y == &t[1]); + assert(a == &t[1]); + ASSERT_NOEXCEPT(a -= 0); + } else { + static_assert(std::is_void_v); + } + + // memory_order::seq_cst + { + auto minus_equals = [](std::atomic_ref const& x, T old_val, T new_val) { x -= (old_val - new_val); }; + auto load = [](std::atomic_ref const& x) { return x.load(); }; + test_seq_cst(minus_equals, load); + } + } +}; + +int main(int, char**) { + TestEachIntegralType()(); + + TestOperatorMinusEquals()(); + TestOperatorMinusEquals()(); + + TestEachPointerType()(); + + TestDoesNotHaveOperatorMinusEquals()(); + TestDoesNotHaveOperatorMinusEquals()(); + TestDoesNotHaveOperatorMinusEquals()(); + + return 0; +} diff --git a/libcxx/test/std/atomics/atomics.ref/operator_plus_equals.pass.cpp b/libcxx/test/std/atomics/atomics.ref/operator_plus_equals.pass.cpp new file mode 100644 index 000000000000..de48ea56f57f --- /dev/null +++ b/libcxx/test/std/atomics/atomics.ref/operator_plus_equals.pass.cpp @@ -0,0 +1,79 @@ +// +// 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 +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14, c++17 +// XFAIL: !has-64-bit-atomics + +// integral-type operator+=(integral-type) const noexcept; +// floating-point-type operator+=(floating-point-type) const noexcept; +// T* operator+=(difference_type) const noexcept; + +#include +#include +#include +#include + +#include "atomic_helpers.h" +#include "test_helper.h" +#include "test_macros.h" + +template +concept has_operator_plus_equals = requires { std::declval() += std::declval(); }; + +template +struct TestDoesNotHaveOperatorPlusEquals { + void operator()() const { static_assert(!has_operator_plus_equals>); } +}; + +template +struct TestOperatorPlusEquals { + void operator()() const { + if constexpr (std::is_arithmetic_v) { + T x(T(1)); + std::atomic_ref const a(x); + + std::same_as decltype(auto) y = (a += T(2)); + assert(y == T(3)); + assert(x == T(3)); + ASSERT_NOEXCEPT(a += T(0)); + } else if constexpr (std::is_pointer_v) { + using U = std::remove_pointer_t; + U t[9] = {}; + T p{&t[1]}; + std::atomic_ref const a(p); + + std::same_as decltype(auto) y = (a += 2); + assert(y == &t[3]); + assert(a == &t[3]); + ASSERT_NOEXCEPT(a += 0); + } else { + static_assert(std::is_void_v); + } + + // memory_order::seq_cst + { + auto plus_equals = [](std::atomic_ref const& x, T old_val, T new_val) { x += (new_val - old_val); }; + auto load = [](std::atomic_ref const& x) { return x.load(); }; + test_seq_cst(plus_equals, load); + } + } +}; + +int main(int, char**) { + TestEachIntegralType()(); + + TestOperatorPlusEquals()(); + TestOperatorPlusEquals()(); + + TestEachPointerType()(); + + TestDoesNotHaveOperatorPlusEquals()(); + TestDoesNotHaveOperatorPlusEquals()(); + TestDoesNotHaveOperatorPlusEquals()(); + + return 0; +} diff --git a/libcxx/test/std/atomics/atomics.ref/required_alignment.pass.cpp b/libcxx/test/std/atomics/atomics.ref/required_alignment.pass.cpp new file mode 100644 index 000000000000..86e0cba4dbf0 --- /dev/null +++ b/libcxx/test/std/atomics/atomics.ref/required_alignment.pass.cpp @@ -0,0 +1,39 @@ +// +// 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 +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14, c++17 + +// static constexpr size_t required_alignment; + +#include +#include +#include + +template +constexpr void check_required_alignment() { + std::same_as decltype(auto) required_alignment = std::atomic_ref::required_alignment; + assert(required_alignment >= alignof(T)); +} + +constexpr bool test() { + check_required_alignment(); + check_required_alignment(); + check_required_alignment(); + struct Empty {}; + check_required_alignment(); + struct Trivial { + int a; + }; + check_required_alignment(); + return true; +} + +int main(int, char**) { + test(); + static_assert(test()); + return 0; +} diff --git a/libcxx/test/std/atomics/atomics.ref/requires-trivially-copyable.verify.cpp b/libcxx/test/std/atomics/atomics.ref/requires-trivially-copyable.verify.cpp new file mode 100644 index 000000000000..9a8b036ffd1f --- /dev/null +++ b/libcxx/test/std/atomics/atomics.ref/requires-trivially-copyable.verify.cpp @@ -0,0 +1,26 @@ +// +// 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 +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14, c++17 + +// + +// template +// class atomic_ref; + +// The program is ill-formed if is_trivially_copyable_v is false. + +#include + +void trivially_copyable() { + struct X { + X() = default; + X(X const&) {} // -> not trivially copyable + } x; + // expected-error-re@*:* {{static assertion failed {{.*}}atomic_ref requires that 'T' be a trivially copyable type}} + std::atomic_ref r(x); +} diff --git a/libcxx/test/std/atomics/atomics.ref/store.pass.cpp b/libcxx/test/std/atomics/atomics.ref/store.pass.cpp new file mode 100644 index 000000000000..ea01a3d02a34 --- /dev/null +++ b/libcxx/test/std/atomics/atomics.ref/store.pass.cpp @@ -0,0 +1,61 @@ +// +// 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 +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14, c++17 +// XFAIL: !has-64-bit-atomics +// XFAIL: !has-1024-bit-atomics + +// void store(T, memory_order = memory_order::seq_cst) const noexcept; + +#include +#include +#include + +#include "atomic_helpers.h" +#include "test_helper.h" +#include "test_macros.h" + +template +struct TestStore { + void operator()() const { + T x(T(1)); + std::atomic_ref const a(x); + + a.store(T(2)); + assert(x == T(2)); + ASSERT_NOEXCEPT(a.store(T(1))); + + a.store(T(3), std::memory_order_seq_cst); + assert(x == T(3)); + ASSERT_NOEXCEPT(a.store(T(0), std::memory_order_seq_cst)); + + // TODO memory_order::relaxed + + // memory_order::seq_cst + { + auto store_no_arg = [](std::atomic_ref const& y, T, T new_val) { y.store(new_val); }; + auto store_with_order = [](std::atomic_ref const& y, T, T new_val) { + y.store(new_val, std::memory_order::seq_cst); + }; + auto load = [](std::atomic_ref const& y) { return y.load(); }; + test_seq_cst(store_no_arg, load); + test_seq_cst(store_with_order, load); + } + + // memory_order::release + { + auto store = [](std::atomic_ref const& y, T, T new_val) { y.store(new_val, std::memory_order::release); }; + auto load = [](std::atomic_ref const& y) { return y.load(std::memory_order::acquire); }; + test_acquire_release(store, load); + } + } +}; + +int main(int, char**) { + TestEachAtomicType()(); + return 0; +} diff --git a/libcxx/test/std/atomics/atomics.ref/test_helper.h b/libcxx/test/std/atomics/atomics.ref/test_helper.h new file mode 100644 index 000000000000..225a70c5a16c --- /dev/null +++ b/libcxx/test/std/atomics/atomics.ref/test_helper.h @@ -0,0 +1,136 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +#ifndef TEST_STD_ATOMICS_ATOMIC_REF_TEST_HELPER_H +#define TEST_STD_ATOMICS_ATOMIC_REF_TEST_HELPER_H + +#include +#include +#include +#include + +#include "test_macros.h" + +#ifndef TEST_HAS_NO_THREADS +# include "make_test_thread.h" +# include +#endif + +template +bool equals(T x, T y) { + return x == y; +} + +template +T make_value(int i) { + assert(i == 0 || i == 1); + if constexpr (std::is_pointer_v) { + // So that pointers returned can be subtracted from one another + static std::remove_const_t> d[2]; + return &d[i]; + } else { + return T(i); + } +} + +// Test that all threads see the exact same sequence of events +// Test will pass 100% if store_op and load_op are correctly +// affecting the memory with seq_cst order +template +void test_seq_cst(StoreOp store_op, LoadOp load_op) { +#ifndef TEST_HAS_NO_THREADS + for (int i = 0; i < 100; ++i) { + T old_value(make_value(0)); + T new_value(make_value(1)); + + T copy_x = old_value; + std::atomic_ref const x(copy_x); + T copy_y = old_value; + std::atomic_ref const y(copy_y); + + std::atomic_bool x_updated_first(false); + std::atomic_bool y_updated_first(false); + + auto t1 = support::make_test_thread([&] { store_op(x, old_value, new_value); }); + + auto t2 = support::make_test_thread([&] { store_op(y, old_value, new_value); }); + + auto t3 = support::make_test_thread([&] { + while (!equals(load_op(x), new_value)) { + std::this_thread::yield(); + } + if (!equals(load_op(y), new_value)) { + x_updated_first.store(true, std::memory_order_relaxed); + } + }); + + auto t4 = support::make_test_thread([&] { + while (!equals(load_op(y), new_value)) { + std::this_thread::yield(); + } + if (!equals(load_op(x), new_value)) { + y_updated_first.store(true, std::memory_order_relaxed); + } + }); + + t1.join(); + t2.join(); + t3.join(); + t4.join(); + // thread 3 and thread 4 cannot see different orders of storing x and y + assert(!(x_updated_first && y_updated_first)); + } +#else + (void)store_op; + (void)load_op; +#endif +} + +// Test that all writes before the store are seen by other threads after the load +// Test will pass 100% if store_op and load_op are correctly +// affecting the memory with acquire-release order +template +void test_acquire_release(StoreOp store_op, LoadOp load_op) { +#ifndef TEST_HAS_NO_THREADS + for (auto i = 0; i < 100; ++i) { + T old_value(make_value(0)); + T new_value(make_value(1)); + + T copy = old_value; + std::atomic_ref const at(copy); + int non_atomic = 5; + + constexpr auto number_of_threads = 8; + std::vector threads; + threads.reserve(number_of_threads); + + for (auto j = 0; j < number_of_threads; ++j) { + threads.push_back(support::make_test_thread([&at, &non_atomic, load_op, new_value] { + while (!equals(load_op(at), new_value)) { + std::this_thread::yield(); + } + // Other thread's writes before the release store are visible + // in this thread's read after the acquire load + assert(non_atomic == 6); + })); + } + + non_atomic = 6; + store_op(at, old_value, new_value); + + for (auto& thread : threads) { + thread.join(); + } + } +#else + (void)store_op; + (void)load_op; +#endif +} + +#endif // TEST_STD_ATOMICS_ATOMIC_REF_TEST_HELPER_H diff --git a/libcxx/test/std/atomics/atomics.ref/wait.pass.cpp b/libcxx/test/std/atomics/atomics.ref/wait.pass.cpp new file mode 100644 index 000000000000..e5310febf5c5 --- /dev/null +++ b/libcxx/test/std/atomics/atomics.ref/wait.pass.cpp @@ -0,0 +1,88 @@ +// +// 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 +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14, c++17 +// UNSUPPORTED: no-threads +// XFAIL: availability-synchronization_library-missing +// XFAIL: !has-64-bit-atomics +// XFAIL: !has-1024-bit-atomics + +// void wait(T, memory_order = memory_order::seq_cst) const noexcept; + +#include +#include +#include + +#include "atomic_helpers.h" +#include "make_test_thread.h" +#include "test_helper.h" +#include "test_macros.h" + +template +struct TestWait { + void operator()() const { + { + T x(T(1)); + std::atomic_ref const a(x); + + assert(a.load() == T(1)); + a.wait(T(0)); + std::thread t1 = support::make_test_thread([&]() { + a.store(T(3)); + a.notify_one(); + }); + a.wait(T(1)); + assert(a.load() == T(3)); + t1.join(); + ASSERT_NOEXCEPT(a.wait(T(0))); + + assert(a.load() == T(3)); + a.wait(T(0), std::memory_order_seq_cst); + std::thread t2 = support::make_test_thread([&]() { + a.store(T(5)); + a.notify_one(); + }); + a.wait(T(3), std::memory_order_seq_cst); + assert(a.load() == T(5)); + t2.join(); + ASSERT_NOEXCEPT(a.wait(T(0), std::memory_order_seq_cst)); + } + + // memory_order::acquire + { + auto store = [](std::atomic_ref const& x, T, T new_val) { x.store(new_val, std::memory_order::release); }; + auto load = [](std::atomic_ref const& x) { + auto result = x.load(std::memory_order::relaxed); + x.wait(T(255), std::memory_order::acquire); + return result; + }; + test_acquire_release(store, load); + } + + // memory_order::seq_cst + { + auto store = [](std::atomic_ref const& x, T, T new_val) { x.store(new_val); }; + auto load_no_arg = [](std::atomic_ref const& x) { + auto result = x.load(std::memory_order::relaxed); + x.wait(T(255)); + return result; + }; + auto load_with_order = [](std::atomic_ref const& x) { + auto result = x.load(std::memory_order::relaxed); + x.wait(T(255), std::memory_order::seq_cst); + return result; + }; + test_seq_cst(store, load_no_arg); + test_seq_cst(store, load_with_order); + } + } +}; + +int main(int, char**) { + TestEachAtomicType()(); + return 0; +} -- GitLab From a5bab70d0667d3bd709720c5c78870b8ad280545 Mon Sep 17 00:00:00 2001 From: Michael Jones Date: Tue, 21 May 2024 16:06:20 -0700 Subject: [PATCH 049/452] [libc] Fix scudo integration test (#92967) When scudo is built with LLVM-libc's headers, certain functions also need to be linked from LLVM-libc. This patch adds those functions to the list to be linked into the specific scudo test, which uses a minimal subset of libc. Fixes #92861 and #59453 --- libc/test/integration/scudo/CMakeLists.txt | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/libc/test/integration/scudo/CMakeLists.txt b/libc/test/integration/scudo/CMakeLists.txt index 8a085b618044..a5f7e3b63d24 100644 --- a/libc/test/integration/scudo/CMakeLists.txt +++ b/libc/test/integration/scudo/CMakeLists.txt @@ -9,6 +9,7 @@ endif() # test will have to link to the LLVM libc startup system. LLVM libc's startup # system is not complete enough to allow this. It is also desireable to # keep the dependencies as minimal as possible. + add_entrypoint_library( libc_for_scudo_integration_test DEPENDS @@ -17,6 +18,9 @@ add_entrypoint_library( libc.src.stdlib.realloc libc.src.stdlib.aligned_alloc libc.src.stdlib.free + libc.src.errno.errno + libc.src.unistd.__llvm_libc_syscall + libc.src.sched.__sched_getcpucount ) add_executable( -- GitLab From b90861498b5b5c06ba24a122b6987738560acf99 Mon Sep 17 00:00:00 2001 From: Heewon Cho Date: Wed, 22 May 2024 08:26:53 +0900 Subject: [PATCH 050/452] [BOLT][NFC] Use const reference in range-based for loop (#92932) Addressing #91195 --- bolt/include/bolt/Passes/StokeInfo.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bolt/include/bolt/Passes/StokeInfo.h b/bolt/include/bolt/Passes/StokeInfo.h index 76417e6a2c3b..a18c2a05d015 100644 --- a/bolt/include/bolt/Passes/StokeInfo.h +++ b/bolt/include/bolt/Passes/StokeInfo.h @@ -87,10 +87,10 @@ struct StokeFuncInfo { << "," << NumBlocks << "," << IsLoopFree << "," << NumLoops << "," << MaxLoopDepth << "," << HotSize << "," << TotalSize << "," << Score << "," << HasCall << ",\"{ "; - for (std::string S : DefIn) + for (const std::string &S : DefIn) Outfile << "%" << S << " "; Outfile << "}\",\"{ "; - for (std::string S : LiveOut) + for (const std::string &S : LiveOut) Outfile << "%" << S << " "; Outfile << "}\"," << HeapOut << "," << StackOut << "," << HasRipAddr << "," << Omitted << "\n"; -- GitLab From e42b799bb28815431f2c5a95f7e13fde3f1b36a1 Mon Sep 17 00:00:00 2001 From: Matheus Izvekov Date: Tue, 21 May 2024 20:27:50 -0300 Subject: [PATCH 051/452] [clang] NFCI: use TemplateArgumentLoc for type-param DefaultArgument (#92854) This is an enabler for a future patch. This allows an type-parameter default argument to be set as an arbitrary TemplateArgument, not just a type. This allows template parameter packs to have default arguments in the AST, even though the language proper doesn't support the syntax for it. This will be used in a later patch which synthesizes template parameter lists with arbitrary default arguments taken from template specializations. There are a few places we used SubsType, because we only had a type, now we use SubstTemplateArgument. SubstTemplateArgument was missing arguments for setting Instantiation location and entity names. Adding those is needed so we don't regress in diagnostics. --- .../ForwardingReferenceOverloadCheck.cpp | 4 +- .../bugprone/IncorrectEnableIfCheck.cpp | 5 +- .../modernize/UseConstraintsCheck.cpp | 8 ++- clang-tools-extra/clangd/Hover.cpp | 8 ++- clang/include/clang/AST/ASTNodeTraverser.h | 2 +- clang/include/clang/AST/DeclTemplate.h | 17 ++--- clang/include/clang/AST/RecursiveASTVisitor.h | 2 +- clang/include/clang/Sema/Sema.h | 4 +- clang/lib/AST/ASTContext.cpp | 3 +- clang/lib/AST/ASTImporter.cpp | 6 +- clang/lib/AST/DeclPrinter.cpp | 3 +- clang/lib/AST/DeclTemplate.cpp | 17 +++-- clang/lib/AST/JSONNodeDumper.cpp | 2 +- clang/lib/AST/ODRDiagsEmitter.cpp | 12 ++-- clang/lib/AST/ODRHash.cpp | 2 +- clang/lib/AST/TypePrinter.cpp | 4 +- clang/lib/ExtractAPI/DeclarationFragments.cpp | 8 +-- clang/lib/Index/IndexDecl.cpp | 3 +- clang/lib/Sema/HLSLExternalSemaSource.cpp | 48 +++++++------ clang/lib/Sema/SemaTemplate.cpp | 69 ++++++++++--------- clang/lib/Sema/SemaTemplateDeduction.cpp | 10 +-- clang/lib/Sema/SemaTemplateInstantiate.cpp | 11 +-- .../lib/Sema/SemaTemplateInstantiateDecl.cpp | 9 ++- clang/lib/Serialization/ASTReaderDecl.cpp | 3 +- clang/lib/Serialization/ASTWriterDecl.cpp | 2 +- clang/tools/libclang/CIndex.cpp | 7 +- clang/unittests/AST/ASTImporterTest.cpp | 2 +- 27 files changed, 144 insertions(+), 127 deletions(-) diff --git a/clang-tools-extra/clang-tidy/bugprone/ForwardingReferenceOverloadCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/ForwardingReferenceOverloadCheck.cpp index 36687a8e761e..c87b3ea7e261 100644 --- a/clang-tools-extra/clang-tidy/bugprone/ForwardingReferenceOverloadCheck.cpp +++ b/clang-tools-extra/clang-tidy/bugprone/ForwardingReferenceOverloadCheck.cpp @@ -54,7 +54,9 @@ AST_MATCHER(QualType, isEnableIf) { AST_MATCHER_P(TemplateTypeParmDecl, hasDefaultArgument, clang::ast_matchers::internal::Matcher, TypeMatcher) { return Node.hasDefaultArgument() && - TypeMatcher.matches(Node.getDefaultArgument(), Finder, Builder); + TypeMatcher.matches( + Node.getDefaultArgument().getArgument().getAsType(), Finder, + Builder); } AST_MATCHER(TemplateDecl, hasAssociatedConstraints) { return Node.hasAssociatedConstraints(); diff --git a/clang-tools-extra/clang-tidy/bugprone/IncorrectEnableIfCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/IncorrectEnableIfCheck.cpp index 09aaf3e31d5d..75f1107904fc 100644 --- a/clang-tools-extra/clang-tidy/bugprone/IncorrectEnableIfCheck.cpp +++ b/clang-tools-extra/clang-tidy/bugprone/IncorrectEnableIfCheck.cpp @@ -19,10 +19,11 @@ namespace { AST_MATCHER_P(TemplateTypeParmDecl, hasUnnamedDefaultArgument, ast_matchers::internal::Matcher, InnerMatcher) { if (Node.getIdentifier() != nullptr || !Node.hasDefaultArgument() || - Node.getDefaultArgumentInfo() == nullptr) + Node.getDefaultArgument().getArgument().isNull()) return false; - TypeLoc DefaultArgTypeLoc = Node.getDefaultArgumentInfo()->getTypeLoc(); + TypeLoc DefaultArgTypeLoc = + Node.getDefaultArgument().getTypeSourceInfo()->getTypeLoc(); return InnerMatcher.matches(DefaultArgTypeLoc, Finder, Builder); } diff --git a/clang-tools-extra/clang-tidy/modernize/UseConstraintsCheck.cpp b/clang-tools-extra/clang-tidy/modernize/UseConstraintsCheck.cpp index 7a021fe14436..ea4d99586c71 100644 --- a/clang-tools-extra/clang-tidy/modernize/UseConstraintsCheck.cpp +++ b/clang-tools-extra/clang-tidy/modernize/UseConstraintsCheck.cpp @@ -177,9 +177,11 @@ matchTrailingTemplateParam(const FunctionTemplateDecl *FunctionTemplate) { dyn_cast(LastParam)) { if (LastTemplateParam->hasDefaultArgument() && LastTemplateParam->getIdentifier() == nullptr) { - return {matchEnableIfSpecialization( - LastTemplateParam->getDefaultArgumentInfo()->getTypeLoc()), - LastTemplateParam}; + return { + matchEnableIfSpecialization(LastTemplateParam->getDefaultArgument() + .getTypeSourceInfo() + ->getTypeLoc()), + LastTemplateParam}; } } return {}; diff --git a/clang-tools-extra/clangd/Hover.cpp b/clang-tools-extra/clangd/Hover.cpp index 06b949bc4a2b..2ec0994e846e 100644 --- a/clang-tools-extra/clangd/Hover.cpp +++ b/clang-tools-extra/clangd/Hover.cpp @@ -247,8 +247,12 @@ fetchTemplateParameters(const TemplateParameterList *Params, if (!TTP->getName().empty()) P.Name = TTP->getNameAsString(); - if (TTP->hasDefaultArgument()) - P.Default = TTP->getDefaultArgument().getAsString(PP); + if (TTP->hasDefaultArgument()) { + P.Default.emplace(); + llvm::raw_string_ostream Out(*P.Default); + TTP->getDefaultArgument().getArgument().print(PP, Out, + /*IncludeType=*/false); + } } else if (const auto *NTTP = dyn_cast(Param)) { P.Type = printType(NTTP, PP); diff --git a/clang/include/clang/AST/ASTNodeTraverser.h b/clang/include/clang/AST/ASTNodeTraverser.h index bf7c204e4ad7..98db1cb57899 100644 --- a/clang/include/clang/AST/ASTNodeTraverser.h +++ b/clang/include/clang/AST/ASTNodeTraverser.h @@ -695,7 +695,7 @@ public: if (const auto *TC = D->getTypeConstraint()) Visit(TC->getImmediatelyDeclaredConstraint()); if (D->hasDefaultArgument()) - Visit(D->getDefaultArgument(), SourceRange(), + Visit(D->getDefaultArgument().getArgument(), SourceRange(), D->getDefaultArgStorage().getInheritedFrom(), D->defaultArgumentWasInherited() ? "inherited from" : "previous"); } diff --git a/clang/include/clang/AST/DeclTemplate.h b/clang/include/clang/AST/DeclTemplate.h index f3d6a321ecf1..07b08b5ed43c 100644 --- a/clang/include/clang/AST/DeclTemplate.h +++ b/clang/include/clang/AST/DeclTemplate.h @@ -1185,7 +1185,7 @@ class TemplateTypeParmDecl final : public TypeDecl, /// The default template argument, if any. using DefArgStorage = - DefaultArgStorage; + DefaultArgStorage; DefArgStorage DefaultArgument; TemplateTypeParmDecl(DeclContext *DC, SourceLocation KeyLoc, @@ -1225,13 +1225,9 @@ public: bool hasDefaultArgument() const { return DefaultArgument.isSet(); } /// Retrieve the default argument, if any. - QualType getDefaultArgument() const { - return DefaultArgument.get()->getType(); - } - - /// Retrieves the default argument's source information, if any. - TypeSourceInfo *getDefaultArgumentInfo() const { - return DefaultArgument.get(); + const TemplateArgumentLoc &getDefaultArgument() const { + static const TemplateArgumentLoc NoneLoc; + return DefaultArgument.isSet() ? *DefaultArgument.get() : NoneLoc; } /// Retrieves the location of the default argument declaration. @@ -1244,9 +1240,8 @@ public: } /// Set the default argument for this template parameter. - void setDefaultArgument(TypeSourceInfo *DefArg) { - DefaultArgument.set(DefArg); - } + void setDefaultArgument(const ASTContext &C, + const TemplateArgumentLoc &DefArg); /// Set that this default argument was inherited from another /// parameter. diff --git a/clang/include/clang/AST/RecursiveASTVisitor.h b/clang/include/clang/AST/RecursiveASTVisitor.h index f5cefedb07e0..659e4cdd1037 100644 --- a/clang/include/clang/AST/RecursiveASTVisitor.h +++ b/clang/include/clang/AST/RecursiveASTVisitor.h @@ -1960,7 +1960,7 @@ DEF_TRAVERSE_DECL(TemplateTypeParmDecl, { TRY_TO(TraverseType(QualType(D->getTypeForDecl(), 0))); TRY_TO(TraverseTemplateTypeParamDeclConstraints(D)); if (D->hasDefaultArgument() && !D->defaultArgumentWasInherited()) - TRY_TO(TraverseTypeLoc(D->getDefaultArgumentInfo()->getTypeLoc())); + TRY_TO(TraverseTemplateArgumentLoc(D->getDefaultArgument())); }) DEF_TRAVERSE_DECL(TypedefDecl, { diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index 8eaf569cb64d..39da728c616c 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -10067,7 +10067,9 @@ public: bool SubstTemplateArgument(const TemplateArgumentLoc &Input, const MultiLevelTemplateArgumentList &TemplateArgs, - TemplateArgumentLoc &Output); + TemplateArgumentLoc &Output, + SourceLocation Loc = {}, + const DeclarationName &Entity = {}); bool SubstTemplateArguments(ArrayRef Args, const MultiLevelTemplateArgumentList &TemplateArgs, diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp index 52eab5feb062..f9902a978aa3 100644 --- a/clang/lib/AST/ASTContext.cpp +++ b/clang/lib/AST/ASTContext.cpp @@ -6494,7 +6494,8 @@ bool ASTContext::isSameDefaultTemplateArgument(const NamedDecl *X, if (!TTPX->hasDefaultArgument() || !TTPY->hasDefaultArgument()) return false; - return hasSameType(TTPX->getDefaultArgument(), TTPY->getDefaultArgument()); + return hasSameType(TTPX->getDefaultArgument().getArgument().getAsType(), + TTPY->getDefaultArgument().getArgument().getAsType()); } if (auto *NTTPX = dyn_cast(X)) { diff --git a/clang/lib/AST/ASTImporter.cpp b/clang/lib/AST/ASTImporter.cpp index 9ff8e1ea78d8..a47dd72a5679 100644 --- a/clang/lib/AST/ASTImporter.cpp +++ b/clang/lib/AST/ASTImporter.cpp @@ -5917,11 +5917,11 @@ ASTNodeImporter::VisitTemplateTypeParmDecl(TemplateTypeParmDecl *D) { } if (D->hasDefaultArgument()) { - Expected ToDefaultArgOrErr = - import(D->getDefaultArgumentInfo()); + Expected ToDefaultArgOrErr = + import(D->getDefaultArgument()); if (!ToDefaultArgOrErr) return ToDefaultArgOrErr.takeError(); - ToD->setDefaultArgument(*ToDefaultArgOrErr); + ToD->setDefaultArgument(ToD->getASTContext(), *ToDefaultArgOrErr); } return ToD; diff --git a/clang/lib/AST/DeclPrinter.cpp b/clang/lib/AST/DeclPrinter.cpp index c5868256b440..bf32aafc3d0a 100644 --- a/clang/lib/AST/DeclPrinter.cpp +++ b/clang/lib/AST/DeclPrinter.cpp @@ -1883,7 +1883,8 @@ void DeclPrinter::VisitTemplateTypeParmDecl(const TemplateTypeParmDecl *TTP) { if (TTP->hasDefaultArgument()) { Out << " = "; - Out << TTP->getDefaultArgument().getAsString(Policy); + TTP->getDefaultArgument().getArgument().print(Policy, Out, + /*IncludeType=*/false); } } diff --git a/clang/lib/AST/DeclTemplate.cpp b/clang/lib/AST/DeclTemplate.cpp index 26765a5da1dc..46bb3e8e5138 100644 --- a/clang/lib/AST/DeclTemplate.cpp +++ b/clang/lib/AST/DeclTemplate.cpp @@ -669,23 +669,30 @@ TemplateTypeParmDecl::CreateDeserialized(const ASTContext &C, GlobalDeclID ID, } SourceLocation TemplateTypeParmDecl::getDefaultArgumentLoc() const { - return hasDefaultArgument() - ? getDefaultArgumentInfo()->getTypeLoc().getBeginLoc() - : SourceLocation(); + return hasDefaultArgument() ? getDefaultArgument().getLocation() + : SourceLocation(); } SourceRange TemplateTypeParmDecl::getSourceRange() const { if (hasDefaultArgument() && !defaultArgumentWasInherited()) return SourceRange(getBeginLoc(), - getDefaultArgumentInfo()->getTypeLoc().getEndLoc()); + getDefaultArgument().getSourceRange().getEnd()); // TypeDecl::getSourceRange returns a range containing name location, which is // wrong for unnamed template parameters. e.g: // it will return <[[typename>]] instead of <[[typename]]> - else if (getDeclName().isEmpty()) + if (getDeclName().isEmpty()) return SourceRange(getBeginLoc()); return TypeDecl::getSourceRange(); } +void TemplateTypeParmDecl::setDefaultArgument( + const ASTContext &C, const TemplateArgumentLoc &DefArg) { + if (DefArg.getArgument().isNull()) + DefaultArgument.set(nullptr); + else + DefaultArgument.set(new (C) TemplateArgumentLoc(DefArg)); +} + unsigned TemplateTypeParmDecl::getDepth() const { return getTypeForDecl()->castAs()->getDepth(); } diff --git a/clang/lib/AST/JSONNodeDumper.cpp b/clang/lib/AST/JSONNodeDumper.cpp index 42608476b1c1..efd3a639d746 100644 --- a/clang/lib/AST/JSONNodeDumper.cpp +++ b/clang/lib/AST/JSONNodeDumper.cpp @@ -1028,7 +1028,7 @@ void JSONNodeDumper::VisitTemplateTypeParmDecl(const TemplateTypeParmDecl *D) { if (D->hasDefaultArgument()) JOS.attributeObject("defaultArg", [=] { - Visit(D->getDefaultArgument(), SourceRange(), + Visit(D->getDefaultArgument().getArgument(), SourceRange(), D->getDefaultArgStorage().getInheritedFrom(), D->defaultArgumentWasInherited() ? "inherited from" : "previous"); }); diff --git a/clang/lib/AST/ODRDiagsEmitter.cpp b/clang/lib/AST/ODRDiagsEmitter.cpp index 5b1cdc16e2ea..97b6c14d9ede 100644 --- a/clang/lib/AST/ODRDiagsEmitter.cpp +++ b/clang/lib/AST/ODRDiagsEmitter.cpp @@ -1409,13 +1409,15 @@ bool ODRDiagsEmitter::diagnoseMismatch( } if (HasFirstDefaultArgument && HasSecondDefaultArgument) { - QualType FirstType = FirstTTPD->getDefaultArgument(); - QualType SecondType = SecondTTPD->getDefaultArgument(); - if (computeODRHash(FirstType) != computeODRHash(SecondType)) { + TemplateArgument FirstTA = + FirstTTPD->getDefaultArgument().getArgument(); + TemplateArgument SecondTA = + SecondTTPD->getDefaultArgument().getArgument(); + if (computeODRHash(FirstTA) != computeODRHash(SecondTA)) { DiagTemplateError(FunctionTemplateParameterDifferentDefaultArgument) - << (i + 1) << FirstType; + << (i + 1) << FirstTA; DiagTemplateNote(FunctionTemplateParameterDifferentDefaultArgument) - << (i + 1) << SecondType; + << (i + 1) << SecondTA; return true; } } diff --git a/clang/lib/AST/ODRHash.cpp b/clang/lib/AST/ODRHash.cpp index 6f04739cf669..18b1e17e0fee 100644 --- a/clang/lib/AST/ODRHash.cpp +++ b/clang/lib/AST/ODRHash.cpp @@ -462,7 +462,7 @@ public: D->hasDefaultArgument() && !D->defaultArgumentWasInherited(); Hash.AddBoolean(hasDefaultArgument); if (hasDefaultArgument) { - AddTemplateArgument(D->getDefaultArgument()); + AddTemplateArgument(D->getDefaultArgument().getArgument()); } Hash.AddBoolean(D->isParameterPack()); diff --git a/clang/lib/AST/TypePrinter.cpp b/clang/lib/AST/TypePrinter.cpp index 87f0a8728d85..981f09410401 100644 --- a/clang/lib/AST/TypePrinter.cpp +++ b/clang/lib/AST/TypePrinter.cpp @@ -2273,8 +2273,8 @@ bool clang::isSubstitutedDefaultArgument(ASTContext &Ctx, TemplateArgument Arg, if (auto *TTPD = dyn_cast(Param)) { return TTPD->hasDefaultArgument() && - isSubstitutedTemplateArgument(Ctx, Arg, TTPD->getDefaultArgument(), - Args, Depth); + isSubstitutedTemplateArgument( + Ctx, Arg, TTPD->getDefaultArgument().getArgument(), Args, Depth); } else if (auto *TTPD = dyn_cast(Param)) { return TTPD->hasDefaultArgument() && isSubstitutedTemplateArgument( diff --git a/clang/lib/ExtractAPI/DeclarationFragments.cpp b/clang/lib/ExtractAPI/DeclarationFragments.cpp index 98b9343924a8..d88e4e0df8ef 100644 --- a/clang/lib/ExtractAPI/DeclarationFragments.cpp +++ b/clang/lib/ExtractAPI/DeclarationFragments.cpp @@ -999,11 +999,11 @@ DeclarationFragmentsBuilder::getFragmentsForTemplateParameters( DeclarationFragments::FragmentKind::GenericParameter); if (TemplateParam->hasDefaultArgument()) { - DeclarationFragments After; + const auto Default = TemplateParam->getDefaultArgument(); Fragments.append(" = ", DeclarationFragments::FragmentKind::Text) - .append(getFragmentsForType(TemplateParam->getDefaultArgument(), - TemplateParam->getASTContext(), After)); - Fragments.append(std::move(After)); + .append(getFragmentsForTemplateArguments( + {Default.getArgument()}, TemplateParam->getASTContext(), + {Default})); } } else if (const auto *NTP = dyn_cast(ParameterArray[i])) { diff --git a/clang/lib/Index/IndexDecl.cpp b/clang/lib/Index/IndexDecl.cpp index 8eb88f5a1e94..058f4aef918a 100644 --- a/clang/lib/Index/IndexDecl.cpp +++ b/clang/lib/Index/IndexDecl.cpp @@ -703,7 +703,8 @@ public: IndexCtx.handleDecl(TP); if (const auto *TTP = dyn_cast(TP)) { if (TTP->hasDefaultArgument()) - IndexCtx.indexTypeSourceInfo(TTP->getDefaultArgumentInfo(), Parent); + handleTemplateArgumentLoc(TTP->getDefaultArgument(), Parent, + TP->getLexicalDeclContext()); if (auto *C = TTP->getTypeConstraint()) IndexCtx.handleReference(C->getNamedConcept(), C->getConceptNameLoc(), Parent, TTP->getLexicalDeclContext()); diff --git a/clang/lib/Sema/HLSLExternalSemaSource.cpp b/clang/lib/Sema/HLSLExternalSemaSource.cpp index bb283c54b3d2..fa8c852ea9e9 100644 --- a/clang/lib/Sema/HLSLExternalSemaSource.cpp +++ b/clang/lib/Sema/HLSLExternalSemaSource.cpp @@ -308,17 +308,18 @@ struct BuiltinTypeDeclBuilder { return *this; } - TemplateParameterListBuilder addTemplateArgumentList(); - BuiltinTypeDeclBuilder &addSimpleTemplateParams(ArrayRef Names); + TemplateParameterListBuilder addTemplateArgumentList(Sema &S); + BuiltinTypeDeclBuilder &addSimpleTemplateParams(Sema &S, + ArrayRef Names); }; struct TemplateParameterListBuilder { BuiltinTypeDeclBuilder &Builder; - ASTContext &AST; + Sema &S; llvm::SmallVector Params; - TemplateParameterListBuilder(BuiltinTypeDeclBuilder &RB) - : Builder(RB), AST(RB.Record->getASTContext()) {} + TemplateParameterListBuilder(Sema &S, BuiltinTypeDeclBuilder &RB) + : Builder(RB), S(S) {} ~TemplateParameterListBuilder() { finalizeTemplateArgs(); } @@ -328,12 +329,15 @@ struct TemplateParameterListBuilder { return *this; unsigned Position = static_cast(Params.size()); auto *Decl = TemplateTypeParmDecl::Create( - AST, Builder.Record->getDeclContext(), SourceLocation(), + S.Context, Builder.Record->getDeclContext(), SourceLocation(), SourceLocation(), /* TemplateDepth */ 0, Position, - &AST.Idents.get(Name, tok::TokenKind::identifier), /* Typename */ false, + &S.Context.Idents.get(Name, tok::TokenKind::identifier), + /* Typename */ false, /* ParameterPack */ false); if (!DefaultValue.isNull()) - Decl->setDefaultArgument(AST.getTrivialTypeSourceInfo(DefaultValue)); + Decl->setDefaultArgument( + S.Context, S.getTrivialTemplateArgumentLoc(DefaultValue, QualType(), + SourceLocation())); Params.emplace_back(Decl); return *this; @@ -342,11 +346,11 @@ struct TemplateParameterListBuilder { BuiltinTypeDeclBuilder &finalizeTemplateArgs() { if (Params.empty()) return Builder; - auto *ParamList = - TemplateParameterList::Create(AST, SourceLocation(), SourceLocation(), - Params, SourceLocation(), nullptr); + auto *ParamList = TemplateParameterList::Create(S.Context, SourceLocation(), + SourceLocation(), Params, + SourceLocation(), nullptr); Builder.Template = ClassTemplateDecl::Create( - AST, Builder.Record->getDeclContext(), SourceLocation(), + S.Context, Builder.Record->getDeclContext(), SourceLocation(), DeclarationName(Builder.Record->getIdentifier()), ParamList, Builder.Record); Builder.Record->setDescribedClassTemplate(Builder.Template); @@ -359,20 +363,22 @@ struct TemplateParameterListBuilder { Params.clear(); QualType T = Builder.Template->getInjectedClassNameSpecialization(); - T = AST.getInjectedClassNameType(Builder.Record, T); + T = S.Context.getInjectedClassNameType(Builder.Record, T); return Builder; } }; } // namespace -TemplateParameterListBuilder BuiltinTypeDeclBuilder::addTemplateArgumentList() { - return TemplateParameterListBuilder(*this); +TemplateParameterListBuilder +BuiltinTypeDeclBuilder::addTemplateArgumentList(Sema &S) { + return TemplateParameterListBuilder(S, *this); } BuiltinTypeDeclBuilder & -BuiltinTypeDeclBuilder::addSimpleTemplateParams(ArrayRef Names) { - TemplateParameterListBuilder Builder = this->addTemplateArgumentList(); +BuiltinTypeDeclBuilder::addSimpleTemplateParams(Sema &S, + ArrayRef Names) { + TemplateParameterListBuilder Builder = this->addTemplateArgumentList(S); for (StringRef Name : Names) Builder.addTypeParameter(Name); return Builder.finalizeTemplateArgs(); @@ -426,7 +432,9 @@ void HLSLExternalSemaSource::defineHLSLVectorAlias() { auto *TypeParam = TemplateTypeParmDecl::Create( AST, HLSLNamespace, SourceLocation(), SourceLocation(), 0, 0, &AST.Idents.get("element", tok::TokenKind::identifier), false, false); - TypeParam->setDefaultArgument(AST.getTrivialTypeSourceInfo(AST.FloatTy)); + TypeParam->setDefaultArgument( + AST, SemaPtr->getTrivialTemplateArgumentLoc( + TemplateArgument(AST.FloatTy), QualType(), SourceLocation())); TemplateParams.emplace_back(TypeParam); @@ -492,7 +500,7 @@ static BuiltinTypeDeclBuilder setupBufferType(CXXRecordDecl *Decl, Sema &S, void HLSLExternalSemaSource::defineHLSLTypesWithForwardDeclarations() { CXXRecordDecl *Decl; Decl = BuiltinTypeDeclBuilder(*SemaPtr, HLSLNamespace, "RWBuffer") - .addSimpleTemplateParams({"element_type"}) + .addSimpleTemplateParams(*SemaPtr, {"element_type"}) .Record; onCompletion(Decl, [this](CXXRecordDecl *Decl) { setupBufferType(Decl, *SemaPtr, ResourceClass::UAV, @@ -503,7 +511,7 @@ void HLSLExternalSemaSource::defineHLSLTypesWithForwardDeclarations() { Decl = BuiltinTypeDeclBuilder(*SemaPtr, HLSLNamespace, "RasterizerOrderedBuffer") - .addSimpleTemplateParams({"element_type"}) + .addSimpleTemplateParams(*SemaPtr, {"element_type"}) .Record; onCompletion(Decl, [this](CXXRecordDecl *Decl) { setupBufferType(Decl, *SemaPtr, ResourceClass::UAV, diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp index 8b82348754fa..f930bd8651d5 100644 --- a/clang/lib/Sema/SemaTemplate.cpp +++ b/clang/lib/Sema/SemaTemplate.cpp @@ -1071,7 +1071,8 @@ NamedDecl *Sema::ActOnTypeParameter(Scope *S, bool Typename, return Param; } - Param->setDefaultArgument(DefaultTInfo); + Param->setDefaultArgument( + Context, TemplateArgumentLoc(DefaultTInfo->getType(), DefaultTInfo)); } return Param; @@ -2321,11 +2322,11 @@ transformTemplateTypeParam(Sema &SemaRef, DeclContext *DC, SemaRef.SubstTypeConstraint(NewTTP, TC, Args, /*EvaluateConstraint=*/true); if (TTP->hasDefaultArgument()) { - TypeSourceInfo *InstantiatedDefaultArg = - SemaRef.SubstType(TTP->getDefaultArgumentInfo(), Args, - TTP->getDefaultArgumentLoc(), TTP->getDeclName()); - if (InstantiatedDefaultArg) - NewTTP->setDefaultArgument(InstantiatedDefaultArg); + TemplateArgumentLoc InstantiatedDefaultArg; + if (!SemaRef.SubstTemplateArgument( + TTP->getDefaultArgument(), Args, InstantiatedDefaultArg, + TTP->getDefaultArgumentLoc(), TTP->getDeclName())) + NewTTP->setDefaultArgument(SemaRef.Context, InstantiatedDefaultArg); } SemaRef.CurrentInstantiationScope->InstantiatedLocal(TTP, NewTTP); return NewTTP; @@ -3578,10 +3579,9 @@ bool Sema::CheckTemplateParameterList(TemplateParameterList *NewParams, = dyn_cast(*NewParam)) { // Check the presence of a default argument here. if (NewTypeParm->hasDefaultArgument() && - DiagnoseDefaultTemplateArgument(*this, TPC, - NewTypeParm->getLocation(), - NewTypeParm->getDefaultArgumentInfo()->getTypeLoc() - .getSourceRange())) + DiagnoseDefaultTemplateArgument( + *this, TPC, NewTypeParm->getLocation(), + NewTypeParm->getDefaultArgument().getSourceRange())) NewTypeParm->removeDefaultArgument(); // Merge default arguments for template type parameters. @@ -6043,22 +6043,26 @@ bool Sema::CheckTemplateTypeArgument( /// /// \param Converted the list of template arguments provided for template /// parameters that precede \p Param in the template parameter list. -/// \returns the substituted template argument, or NULL if an error occurred. -static TypeSourceInfo *SubstDefaultTemplateArgument( +/// +/// \param Output the resulting substituted template argument. +/// +/// \returns true if an error occurred. +static bool SubstDefaultTemplateArgument( Sema &SemaRef, TemplateDecl *Template, SourceLocation TemplateLoc, SourceLocation RAngleLoc, TemplateTypeParmDecl *Param, ArrayRef SugaredConverted, - ArrayRef CanonicalConverted) { - TypeSourceInfo *ArgType = Param->getDefaultArgumentInfo(); + ArrayRef CanonicalConverted, + TemplateArgumentLoc &Output) { + Output = Param->getDefaultArgument(); // If the argument type is dependent, instantiate it now based // on the previously-computed template arguments. - if (ArgType->getType()->isInstantiationDependentType()) { + if (Output.getArgument().isInstantiationDependent()) { Sema::InstantiatingTemplate Inst(SemaRef, TemplateLoc, Param, Template, SugaredConverted, SourceRange(TemplateLoc, RAngleLoc)); if (Inst.isInvalid()) - return nullptr; + return true; // Only substitute for the innermost template argument list. MultiLevelTemplateArgumentList TemplateArgLists(Template, SugaredConverted, @@ -6071,12 +6075,14 @@ static TypeSourceInfo *SubstDefaultTemplateArgument( ForLambdaCallOperator = Rec->isLambda(); Sema::ContextRAII SavedContext(SemaRef, Template->getDeclContext(), !ForLambdaCallOperator); - ArgType = - SemaRef.SubstType(ArgType, TemplateArgLists, - Param->getDefaultArgumentLoc(), Param->getDeclName()); + + if (SemaRef.SubstTemplateArgument(Output, TemplateArgLists, Output, + Param->getDefaultArgumentLoc(), + Param->getDeclName())) + return true; } - return ArgType; + return false; } /// Substitute template arguments into the default template argument for @@ -6199,13 +6205,12 @@ TemplateArgumentLoc Sema::SubstDefaultTemplateArgumentIfAvailable( return TemplateArgumentLoc(); HasDefaultArg = true; - TypeSourceInfo *DI = SubstDefaultTemplateArgument( - *this, Template, TemplateLoc, RAngleLoc, TypeParm, SugaredConverted, - CanonicalConverted); - if (DI) - return TemplateArgumentLoc(TemplateArgument(DI->getType()), DI); - - return TemplateArgumentLoc(); + TemplateArgumentLoc Output; + if (SubstDefaultTemplateArgument(*this, Template, TemplateLoc, RAngleLoc, + TypeParm, SugaredConverted, + CanonicalConverted, Output)) + return TemplateArgumentLoc(); + return Output; } if (NonTypeTemplateParmDecl *NonTypeParm @@ -6788,14 +6793,10 @@ bool Sema::CheckTemplateArgumentList( return diagnoseMissingArgument(*this, TemplateLoc, Template, TTP, NewArgs); - TypeSourceInfo *ArgType = SubstDefaultTemplateArgument( - *this, Template, TemplateLoc, RAngleLoc, TTP, SugaredConverted, - CanonicalConverted); - if (!ArgType) + if (SubstDefaultTemplateArgument(*this, Template, TemplateLoc, RAngleLoc, + TTP, SugaredConverted, + CanonicalConverted, Arg)) return true; - - Arg = TemplateArgumentLoc(TemplateArgument(ArgType->getType()), - ArgType); } else if (NonTypeTemplateParmDecl *NTTP = dyn_cast(*Param)) { if (!hasReachableDefaultArgument(NTTP)) diff --git a/clang/lib/Sema/SemaTemplateDeduction.cpp b/clang/lib/Sema/SemaTemplateDeduction.cpp index 41fd210f29d0..0c348633576d 100644 --- a/clang/lib/Sema/SemaTemplateDeduction.cpp +++ b/clang/lib/Sema/SemaTemplateDeduction.cpp @@ -519,18 +519,14 @@ static NamedDecl *getTemplateParameterWithDefault(Sema &S, NamedDecl *A, switch (A->getKind()) { case Decl::TemplateTypeParm: { auto *T = cast(A); - // FIXME: A TemplateTypeParmDecl's DefaultArgument can't hold a full - // TemplateArgument, so there is currently no way to specify a pack as a - // default argument for these. - if (T->isParameterPack()) - return A; auto *R = TemplateTypeParmDecl::Create( S.Context, A->getDeclContext(), SourceLocation(), SourceLocation(), T->getDepth(), T->getIndex(), T->getIdentifier(), - T->wasDeclaredWithTypename(), /*ParameterPack=*/false, + T->wasDeclaredWithTypename(), T->isParameterPack(), T->hasTypeConstraint()); R->setDefaultArgument( - S.Context.getTrivialTypeSourceInfo(Default.getAsType())); + S.Context, + S.getTrivialTemplateArgumentLoc(Default, QualType(), SourceLocation())); if (R->hasTypeConstraint()) { auto *C = R->getTypeConstraint(); R->setTypeConstraint(C->getConceptReference(), diff --git a/clang/lib/Sema/SemaTemplateInstantiate.cpp b/clang/lib/Sema/SemaTemplateInstantiate.cpp index 07626058c797..abb8a260faab 100644 --- a/clang/lib/Sema/SemaTemplateInstantiate.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiate.cpp @@ -1619,11 +1619,6 @@ namespace { case TemplateArgument::Pack: // Literally rewrite the template argument pack, instead of unpacking // it. - assert( - SemaRef.CodeSynthesisContexts.back().Kind == - Sema::CodeSynthesisContext::BuildingDeductionGuides && - "Transforming a template argument pack is only allowed in building " - "deduction guide"); for (auto &pack : Arg.getPackAsArray()) { TemplateArgumentLoc Input = SemaRef.getTrivialTemplateArgumentLoc( pack, QualType(), SourceLocation{}); @@ -4375,9 +4370,9 @@ Sema::SubstStmt(Stmt *S, const MultiLevelTemplateArgumentList &TemplateArgs) { bool Sema::SubstTemplateArgument( const TemplateArgumentLoc &Input, const MultiLevelTemplateArgumentList &TemplateArgs, - TemplateArgumentLoc &Output) { - TemplateInstantiator Instantiator(*this, TemplateArgs, SourceLocation(), - DeclarationName()); + TemplateArgumentLoc &Output, SourceLocation Loc, + const DeclarationName &Entity) { + TemplateInstantiator Instantiator(*this, TemplateArgs, Loc, Entity); return Instantiator.TransformTemplateArgument(Input, Output); } diff --git a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp index 381d79b2fcd4..38a300332068 100644 --- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -2956,11 +2956,10 @@ Decl *TemplateDeclInstantiator::VisitTemplateTypeParmDecl( } } if (D->hasDefaultArgument() && !D->defaultArgumentWasInherited()) { - TypeSourceInfo *InstantiatedDefaultArg = - SemaRef.SubstType(D->getDefaultArgumentInfo(), TemplateArgs, - D->getDefaultArgumentLoc(), D->getDeclName()); - if (InstantiatedDefaultArg) - Inst->setDefaultArgument(InstantiatedDefaultArg); + TemplateArgumentLoc Output; + if (!SemaRef.SubstTemplateArgument(D->getDefaultArgument(), TemplateArgs, + Output)) + Inst->setDefaultArgument(SemaRef.getASTContext(), Output); } // Introduce this template parameter's instantiation into the instantiation diff --git a/clang/lib/Serialization/ASTReaderDecl.cpp b/clang/lib/Serialization/ASTReaderDecl.cpp index a6254b70560c..d7a9e31b477f 100644 --- a/clang/lib/Serialization/ASTReaderDecl.cpp +++ b/clang/lib/Serialization/ASTReaderDecl.cpp @@ -2695,7 +2695,8 @@ void ASTDeclReader::VisitTemplateTypeParmDecl(TemplateTypeParmDecl *D) { } if (Record.readInt()) - D->setDefaultArgument(readTypeSourceInfo()); + D->setDefaultArgument(Reader.getContext(), + Record.readTemplateArgumentLoc()); } void ASTDeclReader::VisitNonTypeTemplateParmDecl(NonTypeTemplateParmDecl *D) { diff --git a/clang/lib/Serialization/ASTWriterDecl.cpp b/clang/lib/Serialization/ASTWriterDecl.cpp index c2f1d1b44241..b2a214e935aa 100644 --- a/clang/lib/Serialization/ASTWriterDecl.cpp +++ b/clang/lib/Serialization/ASTWriterDecl.cpp @@ -1899,7 +1899,7 @@ void ASTDeclWriter::VisitTemplateTypeParmDecl(TemplateTypeParmDecl *D) { !D->defaultArgumentWasInherited(); Record.push_back(OwnsDefaultArg); if (OwnsDefaultArg) - Record.AddTypeSourceInfo(D->getDefaultArgumentInfo()); + Record.AddTemplateArgumentLoc(D->getDefaultArgument()); if (!TC && !OwnsDefaultArg && D->getDeclContext() == D->getLexicalDeclContext() && diff --git a/clang/tools/libclang/CIndex.cpp b/clang/tools/libclang/CIndex.cpp index f00ba9e3acfc..d0d654568d84 100644 --- a/clang/tools/libclang/CIndex.cpp +++ b/clang/tools/libclang/CIndex.cpp @@ -776,10 +776,9 @@ bool CursorVisitor::VisitTemplateTypeParmDecl(TemplateTypeParmDecl *D) { } // Visit the default argument. - if (D->hasDefaultArgument() && !D->defaultArgumentWasInherited()) - if (TypeSourceInfo *DefArg = D->getDefaultArgumentInfo()) - if (Visit(DefArg->getTypeLoc())) - return true; + if (D->hasDefaultArgument() && !D->defaultArgumentWasInherited() && + VisitTemplateArgumentLoc(D->getDefaultArgument())) + return true; return false; } diff --git a/clang/unittests/AST/ASTImporterTest.cpp b/clang/unittests/AST/ASTImporterTest.cpp index 4ee64de697d3..ba630002c055 100644 --- a/clang/unittests/AST/ASTImporterTest.cpp +++ b/clang/unittests/AST/ASTImporterTest.cpp @@ -1188,7 +1188,7 @@ TEST_P(ASTImporterOptionSpecificTestBase, TemplateTypeParmDeclDefaultArg) { FromTU, templateTypeParmDecl(hasName("T"))); TemplateTypeParmDecl *To = Import(From, Lang_CXX03); ASSERT_TRUE(To->hasDefaultArgument()); - QualType ToArg = To->getDefaultArgument(); + QualType ToArg = To->getDefaultArgument().getArgument().getAsType(); ASSERT_EQ(ToArg, QualType(To->getASTContext().IntTy)); } -- GitLab From 219ea26733f96e0c63796bed8e507f7bb1a02140 Mon Sep 17 00:00:00 2001 From: Heewon Cho Date: Wed, 22 May 2024 08:28:17 +0900 Subject: [PATCH 052/452] [BOLT][NFC] Remove dead initialization code (#92952) Addressing #81441 --- bolt/runtime/instr.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/bolt/runtime/instr.cpp b/bolt/runtime/instr.cpp index 16e0bbd55f90..d1f8a216badc 100644 --- a/bolt/runtime/instr.cpp +++ b/bolt/runtime/instr.cpp @@ -1245,7 +1245,6 @@ void Graph::computeEdgeFrequencies(const uint64_t *Counters, continue; assert(SpanningTreeNodes[Cur].NumInEdges == 1, "must have 1 parent"); - const uint32_t Parent = SpanningTreeNodes[Cur].InEdges[0].Node; const uint32_t ParentEdge = SpanningTreeNodes[Cur].InEdges[0].ID; // Calculate parent edge freq. @@ -1464,9 +1463,8 @@ void visitCallFlowEntry(CallFlowHashTable::MapEntry &Entry, int FD, int openProfile() { // Build the profile name string by appending our PID char Buf[BufSize]; - char *Ptr = Buf; uint64_t PID = __getpid(); - Ptr = strCopy(Buf, __bolt_instr_filename, BufSize); + char *Ptr = strCopy(Buf, __bolt_instr_filename, BufSize); if (__bolt_instr_use_pid) { Ptr = strCopy(Ptr, ".", BufSize - (Ptr - Buf + 1)); Ptr = intToStr(Ptr, PID, 10); -- GitLab From 7630775e3ad34c426cde91732e8e7816c2a1ef5a Mon Sep 17 00:00:00 2001 From: Thomas Fransham Date: Wed, 22 May 2024 00:32:22 +0100 Subject: [PATCH 053/452] Revert "Set ObjectFile's assignment operator to also be deleted like its copy constructor" (#92973) Reverts llvm/llvm-project#92942 --- llvm/include/llvm/Object/ObjectFile.h | 1 - 1 file changed, 1 deletion(-) diff --git a/llvm/include/llvm/Object/ObjectFile.h b/llvm/include/llvm/Object/ObjectFile.h index a50766ccaeb8..8c868c7643ed 100644 --- a/llvm/include/llvm/Object/ObjectFile.h +++ b/llvm/include/llvm/Object/ObjectFile.h @@ -302,7 +302,6 @@ protected: public: ObjectFile() = delete; ObjectFile(const ObjectFile &other) = delete; - ObjectFile &opeartor = (const ObjectFile &other) = delete; uint64_t getCommonSymbolSize(DataRefImpl Symb) const { Expected SymbolFlagsOrErr = getSymbolFlags(Symb); -- GitLab From fd1e511440702aa098f8da97ea35f3f6d9d19cae Mon Sep 17 00:00:00 2001 From: LLVM GN Syncbot Date: Tue, 21 May 2024 23:32:43 +0000 Subject: [PATCH 054/452] [gn build] Port 42ba740afffa --- llvm/utils/gn/secondary/libcxx/include/BUILD.gn | 2 ++ 1 file changed, 2 insertions(+) diff --git a/llvm/utils/gn/secondary/libcxx/include/BUILD.gn b/llvm/utils/gn/secondary/libcxx/include/BUILD.gn index 210b26e8f166..c51e4bf037db 100644 --- a/llvm/utils/gn/secondary/libcxx/include/BUILD.gn +++ b/llvm/utils/gn/secondary/libcxx/include/BUILD.gn @@ -294,6 +294,7 @@ if (current_toolchain == default_toolchain) { "__atomic/atomic_flag.h", "__atomic/atomic_init.h", "__atomic/atomic_lock_free.h", + "__atomic/atomic_ref.h", "__atomic/atomic_sync.h", "__atomic/check_memory_order.h", "__atomic/contention_t.h", @@ -302,6 +303,7 @@ if (current_toolchain == default_toolchain) { "__atomic/is_always_lock_free.h", "__atomic/kill_dependency.h", "__atomic/memory_order.h", + "__atomic/to_gcc_order.h", "__availability", "__bit/bit_cast.h", "__bit/bit_ceil.h", -- GitLab From 79a32609759af317a62184c2c7b1300263a336c8 Mon Sep 17 00:00:00 2001 From: Evgenii Stepanov Date: Tue, 21 May 2024 17:15:08 -0700 Subject: [PATCH 055/452] [hwasan] Remove memory attrs from instrumented functions. (#92974) HWASan instrumentation makes writeonly attribute on function parameters, as well as most memory(*) attributes invalid. This causes miscompilations with LTO, when more optimizations are run after the HWASan pass. --- .../Instrumentation/HWAddressSanitizer.cpp | 8 ++++++++ .../HWAddressSanitizer/mem-attr.ll | 15 +++++++++++++++ 2 files changed, 23 insertions(+) create mode 100644 llvm/test/Instrumentation/HWAddressSanitizer/mem-attr.ll diff --git a/llvm/lib/Transforms/Instrumentation/HWAddressSanitizer.cpp b/llvm/lib/Transforms/Instrumentation/HWAddressSanitizer.cpp index 8d39217992c7..2aa21759d56e 100644 --- a/llvm/lib/Transforms/Instrumentation/HWAddressSanitizer.cpp +++ b/llvm/lib/Transforms/Instrumentation/HWAddressSanitizer.cpp @@ -1589,6 +1589,14 @@ void HWAddressSanitizer::sanitizeFunction(Function &F, assert(!ShadowBase); + // Remove memory attributes that are about to become invalid. + // HWASan checks read from shadow, which invalidates memory(argmem: *) + // Short granule checks on function arguments read from the argument memory + // (last byte of the granule), which invalidates writeonly. + F.removeFnAttr(llvm::Attribute::Memory); + for (auto &A : F.args()) + A.removeAttr(llvm::Attribute::WriteOnly); + BasicBlock::iterator InsertPt = F.getEntryBlock().begin(); IRBuilder<> EntryIRB(&F.getEntryBlock(), InsertPt); emitPrologue(EntryIRB, diff --git a/llvm/test/Instrumentation/HWAddressSanitizer/mem-attr.ll b/llvm/test/Instrumentation/HWAddressSanitizer/mem-attr.ll new file mode 100644 index 000000000000..c0e370f20213 --- /dev/null +++ b/llvm/test/Instrumentation/HWAddressSanitizer/mem-attr.ll @@ -0,0 +1,15 @@ +; Test that HWASan remove writeonly and memory(*) attributes from instrumented functions. +; RUN: opt -S -passes=hwasan %s | FileCheck %s + +target datalayout = "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128-Fn32" +target triple = "aarch64-unknown-linux-android30" + +; CHECK: define dso_local void @test_writeonly(ptr nocapture noundef %p) local_unnamed_addr #0 +define dso_local void @test_writeonly(ptr nocapture noundef writeonly %p) local_unnamed_addr #0 { +entry: + store i32 42, ptr %p, align 4 + ret void +} + +; CHECK: attributes #0 = { sanitize_hwaddress uwtable } +attributes #0 = { sanitize_hwaddress memory(argmem: write) uwtable } -- GitLab From 0170bd5d111f55f45f993a749727ce2815cc0b16 Mon Sep 17 00:00:00 2001 From: Joachim Meyer <5982050+fodinabor@users.noreply.github.com> Date: Tue, 21 May 2024 17:31:50 -0700 Subject: [PATCH 056/452] [MDBuilder] `mergeCallbackEncodings` fails due to inspecting the wrong node (#92466) Given the following metadata as, with `!6` as `ExistingCallbacks` and `!8` as `NewCB`: ``` !6 = !{!7} !7 = !{i64 0, i1 false} !8 = !{i64 2, i64 3, i1 false} ``` The merge function should add `!8` to the list of `!6`, i.e. `!6 = !{!7,!8}`. However, at the moment the check if this is legal, tries to interpret `!7` as integer instead of it's operand. --- llvm/lib/IR/MDBuilder.cpp | 14 +++++------ llvm/unittests/IR/MDBuilderTest.cpp | 39 +++++++++++++++++++++++++++++ 2 files changed, 46 insertions(+), 7 deletions(-) diff --git a/llvm/lib/IR/MDBuilder.cpp b/llvm/lib/IR/MDBuilder.cpp index 0bf41d7cc7c2..bd68db3a6f96 100644 --- a/llvm/lib/IR/MDBuilder.cpp +++ b/llvm/lib/IR/MDBuilder.cpp @@ -86,9 +86,8 @@ MDNode *MDBuilder::createFunctionEntryCount( } MDNode *MDBuilder::createFunctionSectionPrefix(StringRef Prefix) { - return MDNode::get(Context, - {createString("function_section_prefix"), - createString(Prefix)}); + return MDNode::get( + Context, {createString("function_section_prefix"), createString(Prefix)}); } MDNode *MDBuilder::createRange(const APInt &Lo, const APInt &Hi) { @@ -148,9 +147,10 @@ MDNode *MDBuilder::mergeCallbackEncodings(MDNode *ExistingCallbacks, for (unsigned u = 0; u < NumExistingOps; u++) { Ops[u] = ExistingCallbacks->getOperand(u); - auto *OldCBCalleeIdxAsCM = cast(Ops[u]); + auto *OldCBCalleeIdxAsCM = + cast(cast(Ops[u])->getOperand(0)); uint64_t OldCBCalleeIdx = - cast(OldCBCalleeIdxAsCM->getValue())->getZExtValue(); + cast(OldCBCalleeIdxAsCM->getValue())->getZExtValue(); (void)OldCBCalleeIdx; assert(NewCBCalleeIdx != OldCBCalleeIdx && "Cannot map a callback callee index twice!"); @@ -339,8 +339,8 @@ MDNode *MDBuilder::createMutableTBAAAccessTag(MDNode *Tag) { MDNode *MDBuilder::createIrrLoopHeaderWeight(uint64_t Weight) { Metadata *Vals[] = { - createString("loop_header_weight"), - createConstant(ConstantInt::get(Type::getInt64Ty(Context), Weight)), + createString("loop_header_weight"), + createConstant(ConstantInt::get(Type::getInt64Ty(Context), Weight)), }; return MDNode::get(Context, Vals); } diff --git a/llvm/unittests/IR/MDBuilderTest.cpp b/llvm/unittests/IR/MDBuilderTest.cpp index 2b5ab81b6066..4656c70ce9ca 100644 --- a/llvm/unittests/IR/MDBuilderTest.cpp +++ b/llvm/unittests/IR/MDBuilderTest.cpp @@ -127,4 +127,43 @@ TEST_F(MDBuilderTest, createPCSections) { EXPECT_EQ(mdconst::extract(Aux->getOperand(1))->getValue(), C2->getValue()); } +TEST_F(MDBuilderTest, createCallbackAndMerge) { + MDBuilder MDHelper(Context); + auto *CB1 = MDHelper.createCallbackEncoding(0, {1, -1}, false); + auto *CB2 = MDHelper.createCallbackEncoding(2, {-1}, false); + ASSERT_EQ(CB1->getNumOperands(), 4U); + ASSERT_TRUE(isa(CB1->getOperand(0))); + ASSERT_TRUE(isa(CB1->getOperand(1))); + ASSERT_TRUE(isa(CB1->getOperand(2))); + ASSERT_TRUE(isa(CB1->getOperand(3))); + EXPECT_EQ(mdconst::extract(CB1->getOperand(0))->getValue(), 0); + EXPECT_EQ(mdconst::extract(CB1->getOperand(1))->getValue(), 1); + EXPECT_EQ(mdconst::extract(CB1->getOperand(2))->getValue(), -1); + EXPECT_EQ(mdconst::extract(CB1->getOperand(3))->getValue(), + false); + ASSERT_EQ(CB2->getNumOperands(), 3U); + ASSERT_TRUE(isa(CB2->getOperand(0))); + ASSERT_TRUE(isa(CB2->getOperand(1))); + ASSERT_TRUE(isa(CB2->getOperand(2))); + EXPECT_EQ(mdconst::extract(CB2->getOperand(0))->getValue(), 2); + EXPECT_EQ(mdconst::extract(CB2->getOperand(1))->getValue(), -1); + EXPECT_EQ(mdconst::extract(CB2->getOperand(2))->getValue(), + false); + auto *CBList = MDNode::get(Context, {CB1, CB2}); + auto *CB3 = MDHelper.createCallbackEncoding(4, {5}, false); + auto *NewCBList = MDHelper.mergeCallbackEncodings(CBList, CB3); + ASSERT_EQ(NewCBList->getNumOperands(), 3U); + EXPECT_TRUE(NewCBList->getOperand(0) == CB1); + EXPECT_TRUE(NewCBList->getOperand(1) == CB2); + EXPECT_TRUE(NewCBList->getOperand(2) == CB3); + + ASSERT_EQ(CB3->getNumOperands(), 3U); + ASSERT_TRUE(isa(CB3->getOperand(0))); + ASSERT_TRUE(isa(CB3->getOperand(1))); + ASSERT_TRUE(isa(CB3->getOperand(2))); + EXPECT_EQ(mdconst::extract(CB3->getOperand(0))->getValue(), 4); + EXPECT_EQ(mdconst::extract(CB3->getOperand(1))->getValue(), 5); + EXPECT_EQ(mdconst::extract(CB3->getOperand(2))->getValue(), + false); +} } // namespace -- GitLab From 203232ffbd80e9f4631213a3876f14dde155a92d Mon Sep 17 00:00:00 2001 From: Connor Sughrue <55301806+cpsughrue@users.noreply.github.com> Date: Tue, 21 May 2024 20:32:11 -0400 Subject: [PATCH 057/452] [llvm][Support] ListeningSocket::accept returns operation_canceled if FD is set to -1 (#89479) If `::poll` returns and `FD` equals -1, then `ListeningSocket::shutdown` has been called. So, regardless of any other information that could be gleaned from `FDs.revents` or `PollStatus`, it is appropriate to return `std::errc::operation_canceled`. `ListeningSocket::shutdown` copies `FD`'s value to `ObservedFD` then sets `FD` to -1 before canceling `::poll` by calling `::close(ObservedFD)` and writing to the pipe. --- llvm/lib/Support/raw_socket_stream.cpp | 23 +++++++++++-------- .../Support/raw_socket_stream_test.cpp | 19 ++++----------- 2 files changed, 17 insertions(+), 25 deletions(-) diff --git a/llvm/lib/Support/raw_socket_stream.cpp b/llvm/lib/Support/raw_socket_stream.cpp index 14e2308df4d7..549d537709bf 100644 --- a/llvm/lib/Support/raw_socket_stream.cpp +++ b/llvm/lib/Support/raw_socket_stream.cpp @@ -204,17 +204,26 @@ ListeningSocket::accept(std::chrono::milliseconds Timeout) { auto Start = std::chrono::steady_clock::now(); #ifdef _WIN32 PollStatus = WSAPoll(FDs, 2, RemainingTime); - if (PollStatus == SOCKET_ERROR) { #else PollStatus = ::poll(FDs, 2, RemainingTime); +#endif + // If FD equals -1 then ListeningSocket::shutdown has been called and it is + // appropriate to return operation_canceled + if (FD.load() == -1) + return llvm::make_error( + std::make_error_code(std::errc::operation_canceled), + "Accept canceled"); + +#if _WIN32 + if (PollStatus == SOCKET_ERROR) { +#else if (PollStatus == -1) { #endif - // Ignore error if caused by interupting signal std::error_code PollErrCode = getLastSocketErrorCode(); + // Ignore EINTR (signal occured before any request event) and retry if (PollErrCode != std::errc::interrupted) return llvm::make_error(PollErrCode, "FD poll failed"); } - if (PollStatus == 0) return llvm::make_error( std::make_error_code(std::errc::timed_out), @@ -222,13 +231,7 @@ ListeningSocket::accept(std::chrono::milliseconds Timeout) { if (FDs[0].revents & POLLNVAL) return llvm::make_error( - std::make_error_code(std::errc::bad_file_descriptor), - "File descriptor closed by another thread"); - - if (FDs[1].revents & POLLIN) - return llvm::make_error( - std::make_error_code(std::errc::operation_canceled), - "Accept canceled"); + std::make_error_code(std::errc::bad_file_descriptor)); auto Stop = std::chrono::steady_clock::now(); ElapsedTime += diff --git a/llvm/unittests/Support/raw_socket_stream_test.cpp b/llvm/unittests/Support/raw_socket_stream_test.cpp index a8536228666d..c4e8cfbbe7e6 100644 --- a/llvm/unittests/Support/raw_socket_stream_test.cpp +++ b/llvm/unittests/Support/raw_socket_stream_test.cpp @@ -7,7 +7,6 @@ #include "llvm/Testing/Support/Error.h" #include "gtest/gtest.h" #include -#include #include #include @@ -86,13 +85,8 @@ TEST(raw_socket_streamTest, TIMEOUT_PROVIDED) { std::chrono::milliseconds Timeout = std::chrono::milliseconds(100); Expected> MaybeServer = ServerListener.accept(Timeout); - - ASSERT_THAT_EXPECTED(MaybeServer, Failed()); - llvm::Error Err = MaybeServer.takeError(); - llvm::handleAllErrors(std::move(Err), [&](const llvm::StringError &SE) { - std::error_code EC = SE.convertToErrorCode(); - ASSERT_EQ(EC, std::errc::timed_out); - }); + ASSERT_EQ(llvm::errorToErrorCode(MaybeServer.takeError()), + std::errc::timed_out); } TEST(raw_socket_streamTest, FILE_DESCRIPTOR_CLOSED) { @@ -122,12 +116,7 @@ TEST(raw_socket_streamTest, FILE_DESCRIPTOR_CLOSED) { // Wait for the CloseThread to finish CloseThread.join(); - - ASSERT_THAT_EXPECTED(MaybeServer, Failed()); - llvm::Error Err = MaybeServer.takeError(); - llvm::handleAllErrors(std::move(Err), [&](const llvm::StringError &SE) { - std::error_code EC = SE.convertToErrorCode(); - ASSERT_EQ(EC, std::errc::operation_canceled); - }); + ASSERT_EQ(llvm::errorToErrorCode(MaybeServer.takeError()), + std::errc::operation_canceled); } } // namespace -- GitLab From dfdf1c5fe45a82b9c578306f3d7627fd251d63f8 Mon Sep 17 00:00:00 2001 From: Jason Molenda Date: Tue, 21 May 2024 18:00:11 -0700 Subject: [PATCH 058/452] Revert "[clang-repl] Extend the C support. (#89804)" This reverts commit 253c28fa829cee0104c2fc59ed1a958980b5138c. This commit is causing failures on the lldb CI bots, e.g. https://ci.swift.org/view/all/job/llvm.org/view/LLDB/job/as-lldb-cmake/4307/ On my local macOS desktop build, ``` bin/lldb-dotest -p TestImportBuiltinFileID.py Assertion failed: (D->getLexicalDeclContext() == this && "Decl inserted into wrong lexical context"), function addHiddenDecl, file DeclBase.cpp, line 1692. 6 libsystem_c.dylib 0x0000000185f0b8d0 abort + 128 7 libsystem_c.dylib 0x0000000185f0abc8 err + 0 8 liblldb.19.0.0git.dylib 0x00000001311e5800 clang::DeclContext::addHiddenDecl(clang::Decl*) + 120 9 liblldb.19.0.0git.dylib 0x00000001311e5978 clang::DeclContext::addDecl(clang::Decl*) + 32 10 liblldb.19.0.0git.dylib 0x000000012f617b48 clang::Sema::ActOnStartTopLevelStmtDecl(clang::Scope*) + 64 11 liblldb.19.0.0git.dylib 0x000000012eaf76c8 clang::Parser::ParseTopLevelStmtDecl() + 208 12 liblldb.19.0.0git.dylib 0x000000012ec051fc clang::Parser::ParseExternalDeclaration(clang::ParsedAttributes&, clang::ParsedAttributes&, clang::ParsingDeclSpec*) + 3412 13 liblldb.19.0.0git.dylib 0x000000012ec03274 clang::Parser::ParseTopLevelDecl(clang::OpaquePtr&, clang::Sema::ModuleImportState&) + 2020 14 liblldb.19.0.0git.dylib 0x000000012eaca860 clang::ParseAST(clang::Sema&, bool, bool) + 604 15 liblldb.19.0.0git.dylib 0x000000012e8554c0 clang::ASTFrontendAction::ExecuteAction() + 308 16 liblldb.19.0.0git.dylib 0x000000012e854c78 clang::FrontendAction::Execute() + 124 17 liblldb.19.0.0git.dylib 0x000000012e76dcfc clang::CompilerInstance::ExecuteAction(clang::FrontendAction&) + 984 18 liblldb.19.0.0git.dylib 0x000000012e784500 compileModuleImpl(clang::CompilerInstance&, clang::SourceLocation, llvm::StringRef, clang::FrontendInputFile, llvm::StringRef, llvm::StringRef, llvm::function_ref, llvm::function_ref)::$_1::operator()() const + 52 ``` Reverting until Vassil has a chance to look int oit. --- clang/lib/Interpreter/IncrementalParser.cpp | 13 ++----------- clang/lib/Sema/SemaDecl.cpp | 10 +++------- clang/test/Interpreter/execute.c | 21 --------------------- 3 files changed, 5 insertions(+), 39 deletions(-) delete mode 100644 clang/test/Interpreter/execute.c diff --git a/clang/lib/Interpreter/IncrementalParser.cpp b/clang/lib/Interpreter/IncrementalParser.cpp index 5bc8385d874a..ef90fe9e6f54 100644 --- a/clang/lib/Interpreter/IncrementalParser.cpp +++ b/clang/lib/Interpreter/IncrementalParser.cpp @@ -387,7 +387,8 @@ std::unique_ptr IncrementalParser::GenModule() { void IncrementalParser::CleanUpPTU(PartialTranslationUnit &PTU) { TranslationUnitDecl *MostRecentTU = PTU.TUPart; - if (StoredDeclsMap *Map = MostRecentTU->getPrimaryContext()->getLookupPtr()) { + TranslationUnitDecl *FirstTU = MostRecentTU->getFirstDecl(); + if (StoredDeclsMap *Map = FirstTU->getPrimaryContext()->getLookupPtr()) { for (auto &&[Key, List] : *Map) { DeclContextLookupResult R = List.getLookupResult(); std::vector NamedDeclsToRemove; @@ -406,16 +407,6 @@ void IncrementalParser::CleanUpPTU(PartialTranslationUnit &PTU) { } } } - - // FIXME: We should de-allocate MostRecentTU - for (Decl *D : MostRecentTU->decls()) { - auto *ND = dyn_cast(D); - if (!ND) - continue; - // Check if we need to clean up the IdResolver chain. - if (ND->getDeclName().getFETokenInfo()) - getCI()->getSema().IdResolver.RemoveDecl(ND); - } } llvm::StringRef IncrementalParser::GetMangledName(GlobalDecl GD) const { diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index 6e60ec761b25..8049ddfed872 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -2282,13 +2282,9 @@ void Sema::ActOnPopScope(SourceLocation Loc, Scope *S) { if (LabelDecl *LD = dyn_cast(D)) CheckPoppedLabel(LD, *this, addDiag); - // Partial translation units that are created in incremental processing must - // not clean up the IdResolver because PTUs should take into account the - // declarations that came from previous PTUs. - if (!PP.isIncrementalProcessingEnabled()) - IdResolver.RemoveDecl(D); - - // Warn on it if we are shadowing a declaration. + // Remove this name from our lexical scope, and warn on it if we haven't + // already. + IdResolver.RemoveDecl(D); auto ShadowI = ShadowingDecls.find(D); if (ShadowI != ShadowingDecls.end()) { if (const auto *FD = dyn_cast(ShadowI->second)) { diff --git a/clang/test/Interpreter/execute.c b/clang/test/Interpreter/execute.c deleted file mode 100644 index 44a3a32c9301..000000000000 --- a/clang/test/Interpreter/execute.c +++ /dev/null @@ -1,21 +0,0 @@ -// REQUIRES: host-supports-jit -// UNSUPPORTED: system-aix - -// RUN: cat %s | clang-repl -Xcc -xc -Xcc -Xclang -Xcc -verify | FileCheck %s -// RUN: cat %s | clang-repl -Xcc -xc -Xcc -O2 -Xcc -Xclang -Xcc -verify| FileCheck %s -int printf(const char *, ...); -int i = 42; err // expected-error{{use of undeclared identifier}} -int i = 42; -struct S { float f; struct S *m;} s = {1.0, 0}; -// FIXME: Making foo inline fails to emit the function. -int foo() { return 42; } -void run() { \ - printf("i = %d\n", i); \ - printf("S[f=%f, m=0x%llx]\n", s.f, (unsigned long long)s.m); \ - int r3 = foo(); \ -} -run(); -// CHECK: i = 42 -// CHECK-NEXT: S[f=1.000000, m=0x0] - -%quit -- GitLab From f0d1ae83b046ff0eeffc72a103f7c8b01ad33787 Mon Sep 17 00:00:00 2001 From: csstormq Date: Wed, 22 May 2024 09:23:00 +0800 Subject: [PATCH 059/452] [llvm][ScheduleDAG] SUnit::biasCriticalPath() does not find the critical path consistently (#92368) Fix https://github.com/llvm/llvm-project/issues/38037 --- llvm/lib/CodeGen/ScheduleDAG.cpp | 4 +- .../test/CodeGen/X86/misched-critical-path.ll | 240 ++++++++++++++++++ 2 files changed, 243 insertions(+), 1 deletion(-) create mode 100644 llvm/test/CodeGen/X86/misched-critical-path.ll diff --git a/llvm/lib/CodeGen/ScheduleDAG.cpp b/llvm/lib/CodeGen/ScheduleDAG.cpp index de8e6f63794d..8d9a5041fc2f 100644 --- a/llvm/lib/CodeGen/ScheduleDAG.cpp +++ b/llvm/lib/CodeGen/ScheduleDAG.cpp @@ -331,8 +331,10 @@ void SUnit::biasCriticalPath() { unsigned MaxDepth = BestI->getSUnit()->getDepth(); for (SUnit::pred_iterator I = std::next(BestI), E = Preds.end(); I != E; ++I) { - if (I->getKind() == SDep::Data && I->getSUnit()->getDepth() > MaxDepth) + if (I->getKind() == SDep::Data && I->getSUnit()->getDepth() > MaxDepth) { + MaxDepth = I->getSUnit()->getDepth(); BestI = I; + } } if (BestI != Preds.begin()) std::swap(*Preds.begin(), *BestI); diff --git a/llvm/test/CodeGen/X86/misched-critical-path.ll b/llvm/test/CodeGen/X86/misched-critical-path.ll new file mode 100644 index 000000000000..909692aca2b0 --- /dev/null +++ b/llvm/test/CodeGen/X86/misched-critical-path.ll @@ -0,0 +1,240 @@ +; RUN: llc < %s -mtriple=x86_64-apple-darwin8 -misched-print-dags -o - 2>&1 > /dev/null | FileCheck %s + +target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128" + +@sc = common global i8 0 +@uc = common global i8 0 +@ss = common global i16 0 +@us = common global i16 0 +@si = common global i32 0 +@ui = common global i32 0 +@sl = common global i64 0 +@ul = common global i64 0 +@sll = common global i64 0 +@ull = common global i64 0 + +; Regression Test for PR92368. +; +; CHECK: SU(75): CMP8rr %49:gr8, %48:gr8, implicit-def $eflags +; CHECK: Predecessors: +; CHECK-NEXT: SU(73): Data Latency=0 Reg=%49 +; CHECK-NEXT: SU(74): Out Latency=0 +; CHECK-NEXT: SU(72): Out Latency=0 +; CHECK-NEXT: SU(70): Data Latency=4 Reg=%48 +define void @misched_bug() nounwind { +entry: + %0 = load i8, i8* @sc, align 1 + %1 = zext i8 %0 to i32 + %2 = load i8, i8* @uc, align 1 + %3 = zext i8 %2 to i32 + %4 = trunc i32 %3 to i8 + %5 = trunc i32 %1 to i8 + %pair6 = cmpxchg i8* @sc, i8 %4, i8 %5 monotonic monotonic + %6 = extractvalue { i8, i1 } %pair6, 0 + store i8 %6, i8* @sc, align 1 + %7 = load i8, i8* @sc, align 1 + %8 = zext i8 %7 to i32 + %9 = load i8, i8* @uc, align 1 + %10 = zext i8 %9 to i32 + %11 = trunc i32 %10 to i8 + %12 = trunc i32 %8 to i8 + %pair13 = cmpxchg i8* @uc, i8 %11, i8 %12 monotonic monotonic + %13 = extractvalue { i8, i1 } %pair13, 0 + store i8 %13, i8* @uc, align 1 + %14 = load i8, i8* @sc, align 1 + %15 = sext i8 %14 to i16 + %16 = zext i16 %15 to i32 + %17 = load i8, i8* @uc, align 1 + %18 = zext i8 %17 to i32 + %19 = bitcast i8* bitcast (i16* @ss to i8*) to i16* + %20 = trunc i32 %18 to i16 + %21 = trunc i32 %16 to i16 + %pair22 = cmpxchg i16* %19, i16 %20, i16 %21 monotonic monotonic + %22 = extractvalue { i16, i1 } %pair22, 0 + store i16 %22, i16* @ss, align 2 + %23 = load i8, i8* @sc, align 1 + %24 = sext i8 %23 to i16 + %25 = zext i16 %24 to i32 + %26 = load i8, i8* @uc, align 1 + %27 = zext i8 %26 to i32 + %28 = bitcast i8* bitcast (i16* @us to i8*) to i16* + %29 = trunc i32 %27 to i16 + %30 = trunc i32 %25 to i16 + %pair31 = cmpxchg i16* %28, i16 %29, i16 %30 monotonic monotonic + %31 = extractvalue { i16, i1 } %pair31, 0 + store i16 %31, i16* @us, align 2 + %32 = load i8, i8* @sc, align 1 + %33 = sext i8 %32 to i32 + %34 = load i8, i8* @uc, align 1 + %35 = zext i8 %34 to i32 + %36 = bitcast i8* bitcast (i32* @si to i8*) to i32* + %pair37 = cmpxchg i32* %36, i32 %35, i32 %33 monotonic monotonic + %37 = extractvalue { i32, i1 } %pair37, 0 + store i32 %37, i32* @si, align 4 + %38 = load i8, i8* @sc, align 1 + %39 = sext i8 %38 to i32 + %40 = load i8, i8* @uc, align 1 + %41 = zext i8 %40 to i32 + %42 = bitcast i8* bitcast (i32* @ui to i8*) to i32* + %pair43 = cmpxchg i32* %42, i32 %41, i32 %39 monotonic monotonic + %43 = extractvalue { i32, i1 } %pair43, 0 + store i32 %43, i32* @ui, align 4 + %44 = load i8, i8* @sc, align 1 + %45 = sext i8 %44 to i64 + %46 = load i8, i8* @uc, align 1 + %47 = zext i8 %46 to i64 + %48 = bitcast i8* bitcast (i64* @sl to i8*) to i64* + %pair49 = cmpxchg i64* %48, i64 %47, i64 %45 monotonic monotonic + %49 = extractvalue { i64, i1 } %pair49, 0 + store i64 %49, i64* @sl, align 8 + %50 = load i8, i8* @sc, align 1 + %51 = sext i8 %50 to i64 + %52 = load i8, i8* @uc, align 1 + %53 = zext i8 %52 to i64 + %54 = bitcast i8* bitcast (i64* @ul to i8*) to i64* + %pair55 = cmpxchg i64* %54, i64 %53, i64 %51 monotonic monotonic + %55 = extractvalue { i64, i1 } %pair55, 0 + store i64 %55, i64* @ul, align 8 + %56 = load i8, i8* @sc, align 1 + %57 = sext i8 %56 to i64 + %58 = load i8, i8* @uc, align 1 + %59 = zext i8 %58 to i64 + %60 = bitcast i8* bitcast (i64* @sll to i8*) to i64* + %pair61 = cmpxchg i64* %60, i64 %59, i64 %57 monotonic monotonic + %61 = extractvalue { i64, i1 } %pair61, 0 + store i64 %61, i64* @sll, align 8 + %62 = load i8, i8* @sc, align 1 + %63 = sext i8 %62 to i64 + %64 = load i8, i8* @uc, align 1 + %65 = zext i8 %64 to i64 + %66 = bitcast i8* bitcast (i64* @ull to i8*) to i64* + %pair67 = cmpxchg i64* %66, i64 %65, i64 %63 monotonic monotonic + %67 = extractvalue { i64, i1 } %pair67, 0 + store i64 %67, i64* @ull, align 8 + %68 = load i8, i8* @sc, align 1 + %69 = zext i8 %68 to i32 + %70 = load i8, i8* @uc, align 1 + %71 = zext i8 %70 to i32 + %72 = trunc i32 %71 to i8 + %73 = trunc i32 %69 to i8 + %pair74 = cmpxchg i8* @sc, i8 %72, i8 %73 monotonic monotonic + %74 = extractvalue { i8, i1 } %pair74, 0 + %75 = icmp eq i8 %74, %72 + %76 = zext i1 %75 to i8 + %77 = zext i8 %76 to i32 + store i32 %77, i32* @ui, align 4 + %78 = load i8, i8* @sc, align 1 + %79 = zext i8 %78 to i32 + %80 = load i8, i8* @uc, align 1 + %81 = zext i8 %80 to i32 + %82 = trunc i32 %81 to i8 + %83 = trunc i32 %79 to i8 + %pair84 = cmpxchg i8* @uc, i8 %82, i8 %83 monotonic monotonic + %84 = extractvalue { i8, i1 } %pair84, 0 + %85 = icmp eq i8 %84, %82 + %86 = zext i1 %85 to i8 + %87 = zext i8 %86 to i32 + store i32 %87, i32* @ui, align 4 + %88 = load i8, i8* @sc, align 1 + %89 = sext i8 %88 to i16 + %90 = zext i16 %89 to i32 + %91 = load i8, i8* @uc, align 1 + %92 = zext i8 %91 to i32 + %93 = trunc i32 %92 to i8 + %94 = trunc i32 %90 to i8 + %pair95 = cmpxchg i8* bitcast (i16* @ss to i8*), i8 %93, i8 %94 monotonic monotonic + %95 = extractvalue { i8, i1 } %pair95, 0 + %96 = icmp eq i8 %95, %93 + %97 = zext i1 %96 to i8 + %98 = zext i8 %97 to i32 + store i32 %98, i32* @ui, align 4 + %99 = load i8, i8* @sc, align 1 + %100 = sext i8 %99 to i16 + %101 = zext i16 %100 to i32 + %102 = load i8, i8* @uc, align 1 + %103 = zext i8 %102 to i32 + %104 = trunc i32 %103 to i8 + %105 = trunc i32 %101 to i8 + %pair106 = cmpxchg i8* bitcast (i16* @us to i8*), i8 %104, i8 %105 monotonic monotonic + %106 = extractvalue { i8, i1 } %pair106, 0 + %107 = icmp eq i8 %106, %104 + %108 = zext i1 %107 to i8 + %109 = zext i8 %108 to i32 + store i32 %109, i32* @ui, align 4 + %110 = load i8, i8* @sc, align 1 + %111 = sext i8 %110 to i32 + %112 = load i8, i8* @uc, align 1 + %113 = zext i8 %112 to i32 + %114 = trunc i32 %113 to i8 + %115 = trunc i32 %111 to i8 + %pair116 = cmpxchg i8* bitcast (i32* @si to i8*), i8 %114, i8 %115 monotonic monotonic + %116 = extractvalue { i8, i1 } %pair116, 0 + %117 = icmp eq i8 %116, %114 + %118 = zext i1 %117 to i8 + %119 = zext i8 %118 to i32 + store i32 %119, i32* @ui, align 4 + %120 = load i8, i8* @sc, align 1 + %121 = sext i8 %120 to i32 + %122 = load i8, i8* @uc, align 1 + %123 = zext i8 %122 to i32 + %124 = trunc i32 %123 to i8 + %125 = trunc i32 %121 to i8 + %pair126 = cmpxchg i8* bitcast (i32* @ui to i8*), i8 %124, i8 %125 monotonic monotonic + %126 = extractvalue { i8, i1 } %pair126, 0 + %127 = icmp eq i8 %126, %124 + %128 = zext i1 %127 to i8 + %129 = zext i8 %128 to i32 + store i32 %129, i32* @ui, align 4 + %130 = load i8, i8* @sc, align 1 + %131 = sext i8 %130 to i64 + %132 = load i8, i8* @uc, align 1 + %133 = zext i8 %132 to i64 + %134 = trunc i64 %133 to i8 + %135 = trunc i64 %131 to i8 + %pair136 = cmpxchg i8* bitcast (i64* @sl to i8*), i8 %134, i8 %135 monotonic monotonic + %136 = extractvalue { i8, i1 } %pair136, 0 + %137 = icmp eq i8 %136, %134 + %138 = zext i1 %137 to i8 + %139 = zext i8 %138 to i32 + store i32 %139, i32* @ui, align 4 + %140 = load i8, i8* @sc, align 1 + %141 = sext i8 %140 to i64 + %142 = load i8, i8* @uc, align 1 + %143 = zext i8 %142 to i64 + %144 = trunc i64 %143 to i8 + %145 = trunc i64 %141 to i8 + %pair146 = cmpxchg i8* bitcast (i64* @ul to i8*), i8 %144, i8 %145 monotonic monotonic + %146 = extractvalue { i8, i1 } %pair146, 0 + %147 = icmp eq i8 %146, %144 + %148 = zext i1 %147 to i8 + %149 = zext i8 %148 to i32 + store i32 %149, i32* @ui, align 4 + %150 = load i8, i8* @sc, align 1 + %151 = sext i8 %150 to i64 + %152 = load i8, i8* @uc, align 1 + %153 = zext i8 %152 to i64 + %154 = trunc i64 %153 to i8 + %155 = trunc i64 %151 to i8 + %pair156 = cmpxchg i8* bitcast (i64* @sll to i8*), i8 %154, i8 %155 monotonic monotonic + %156 = extractvalue { i8, i1 } %pair156, 0 + %157 = icmp eq i8 %156, %154 + %158 = zext i1 %157 to i8 + %159 = zext i8 %158 to i32 + store i32 %159, i32* @ui, align 4 + %160 = load i8, i8* @sc, align 1 + %161 = sext i8 %160 to i64 + %162 = load i8, i8* @uc, align 1 + %163 = zext i8 %162 to i64 + %164 = trunc i64 %163 to i8 + %165 = trunc i64 %161 to i8 + %pair166 = cmpxchg i8* bitcast (i64* @ull to i8*), i8 %164, i8 %165 monotonic monotonic + %166 = extractvalue { i8, i1 } %pair166, 0 + %167 = icmp eq i8 %166, %164 + %168 = zext i1 %167 to i8 + %169 = zext i8 %168 to i32 + store i32 %169, i32* @ui, align 4 + br label %return + +return: ; preds = %entry + ret void +} -- GitLab From a9b67490b2baaa311100a64191792186ea5f2c1e Mon Sep 17 00:00:00 2001 From: Amir Ayupov Date: Tue, 21 May 2024 18:54:15 -0700 Subject: [PATCH 060/452] [BOLT] Report adjusted program stats from perf2bolt in BAT mode (#91683) --- bolt/include/bolt/Passes/BinaryPasses.h | 6 +++++- bolt/lib/Passes/BinaryPasses.cpp | 12 +++++++++++- bolt/lib/Profile/DataAggregator.cpp | 3 ++- bolt/test/X86/bolt-address-translation-yaml.test | 5 ++++- 4 files changed, 22 insertions(+), 4 deletions(-) diff --git a/bolt/include/bolt/Passes/BinaryPasses.h b/bolt/include/bolt/Passes/BinaryPasses.h index 5d7692559eda..a07c9130041f 100644 --- a/bolt/include/bolt/Passes/BinaryPasses.h +++ b/bolt/include/bolt/Passes/BinaryPasses.h @@ -16,6 +16,7 @@ #include "bolt/Core/BinaryContext.h" #include "bolt/Core/BinaryFunction.h" #include "bolt/Core/DynoStats.h" +#include "bolt/Profile/BoltAddressTranslation.h" #include "llvm/Support/CommandLine.h" #include #include @@ -399,8 +400,11 @@ public: /// Prints a list of the top 100 functions sorted by a set of /// dyno stats categories. class PrintProgramStats : public BinaryFunctionPass { + BoltAddressTranslation *BAT = nullptr; + public: - explicit PrintProgramStats() : BinaryFunctionPass(false) {} + explicit PrintProgramStats(BoltAddressTranslation *BAT = nullptr) + : BinaryFunctionPass(false), BAT(BAT) {} const char *getName() const override { return "print-stats"; } bool shouldPrint(const BinaryFunction &) const override { return false; } diff --git a/bolt/lib/Passes/BinaryPasses.cpp b/bolt/lib/Passes/BinaryPasses.cpp index 298ba29ff5b3..11e22dea71fb 100644 --- a/bolt/lib/Passes/BinaryPasses.cpp +++ b/bolt/lib/Passes/BinaryPasses.cpp @@ -1390,9 +1390,19 @@ Error PrintProgramStats::runOnFunctions(BinaryContext &BC) { if (Function.isPLTFunction()) continue; + // Adjustment for BAT mode: the profile for BOLT split fragments is combined + // so only count the hot fragment. + const uint64_t Address = Function.getAddress(); + bool IsHotParentOfBOLTSplitFunction = !Function.getFragments().empty() && + BAT && BAT->isBATFunction(Address) && + !BAT->fetchParentAddress(Address); + ++NumRegularFunctions; - if (!Function.isSimple()) { + // In BOLTed binaries split functions are non-simple (due to non-relocation + // mode), but the original function is known to be simple and we have a + // valid profile for it. + if (!Function.isSimple() && !IsHotParentOfBOLTSplitFunction) { if (Function.hasProfile()) ++NumNonSimpleProfiledFunctions; continue; diff --git a/bolt/lib/Profile/DataAggregator.cpp b/bolt/lib/Profile/DataAggregator.cpp index f55caa7f03f7..efda4932c09f 100644 --- a/bolt/lib/Profile/DataAggregator.cpp +++ b/bolt/lib/Profile/DataAggregator.cpp @@ -613,7 +613,8 @@ Error DataAggregator::readProfile(BinaryContext &BC) { if (std::error_code EC = writeBATYAML(BC, opts::SaveProfile)) report_error("cannot create output data file", EC); } - BC.logBOLTErrorsAndQuitOnFatal(PrintProgramStats().runOnFunctions(BC)); + PrintProgramStats PPS(BAT); + BC.logBOLTErrorsAndQuitOnFatal(PPS.runOnFunctions(BC)); } return Error::success(); diff --git a/bolt/test/X86/bolt-address-translation-yaml.test b/bolt/test/X86/bolt-address-translation-yaml.test index e21513b7dfe5..9f2c2ef3ab98 100644 --- a/bolt/test/X86/bolt-address-translation-yaml.test +++ b/bolt/test/X86/bolt-address-translation-yaml.test @@ -31,7 +31,8 @@ RUN: perf2bolt %t.out --pa -p %p/Inputs/blarge_new_bat.preagg.txt -w %t.yaml -o RUN: 2>&1 | FileCheck --check-prefix READ-BAT-CHECK %s RUN: FileCheck --input-file %t.yaml --check-prefix YAML-BAT-CHECK %s # Check that YAML converted from fdata matches YAML created directly with BAT. -RUN: llvm-bolt %t.exe -data %t.fdata -w %t.yaml-fdata -o /dev/null +RUN: llvm-bolt %t.exe -data %t.fdata -w %t.yaml-fdata -o /dev/null \ +RUN: 2>&1 | FileCheck --check-prefix READ-BAT-FDATA-CHECK %s RUN: FileCheck --input-file %t.yaml-fdata --check-prefix YAML-BAT-CHECK %s # Test resulting YAML profile with the original binary (no-stale mode) @@ -45,6 +46,8 @@ WRITE-BAT-CHECK: BOLT-INFO: BAT section size (bytes): 384 READ-BAT-CHECK-NOT: BOLT-ERROR: unable to save profile in YAML format for input file processed by BOLT READ-BAT-CHECK: BOLT-INFO: Parsed 5 BAT entries READ-BAT-CHECK: PERF2BOLT: read 79 aggregated LBR entries +READ-BAT-CHECK: BOLT-INFO: 5 out of 21 functions in the binary (23.8%) have non-empty execution profile +READ-BAT-FDATA-CHECK: BOLT-INFO: 5 out of 16 functions in the binary (31.2%) have non-empty execution profile YAML-BAT-CHECK: functions: # Function not covered by BAT - has insns in basic block -- GitLab From c2e0afe95efd495f5c76bbea410730a321a69e9c Mon Sep 17 00:00:00 2001 From: Yuxuan Chen Date: Tue, 21 May 2024 18:57:45 -0700 Subject: [PATCH 061/452] [Coroutines][NFC] Remove @llvm.coro.id.async intrinsics from CoroElide (#92956) --- llvm/lib/Transforms/Coroutines/CoroElide.cpp | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/llvm/lib/Transforms/Coroutines/CoroElide.cpp b/llvm/lib/Transforms/Coroutines/CoroElide.cpp index bb244489e4c2..74b5ccb7b9b7 100644 --- a/llvm/lib/Transforms/Coroutines/CoroElide.cpp +++ b/llvm/lib/Transforms/Coroutines/CoroElide.cpp @@ -464,13 +464,9 @@ bool CoroIdElider::attemptElide() { return true; } -static bool declaresCoroElideIntrinsics(Module &M) { - return coro::declaresIntrinsics(M, {"llvm.coro.id", "llvm.coro.id.async"}); -} - PreservedAnalyses CoroElidePass::run(Function &F, FunctionAnalysisManager &AM) { auto &M = *F.getParent(); - if (!declaresCoroElideIntrinsics(M)) + if (!coro::declaresIntrinsics(M, {"llvm.coro.id"})) return PreservedAnalyses::all(); FunctionElideInfo FEI{&F}; -- GitLab From 511077df763752fd2c187e4ca1a3ada335b77804 Mon Sep 17 00:00:00 2001 From: Wu Yingcong Date: Tue, 21 May 2024 19:15:22 -0700 Subject: [PATCH 062/452] [sanitizers] Bump malloc limit to 1TB for MSAN, LSAN & DFSAN (#89728) We already have `const uptr kMaxAllowedMallocSize = 1ULL << 40;` set for ASAN, HWASAN, memprof, TSAN. This patch bumps the malloc limit for MSAN, LSAN and DFSAN to 1TB as well. 8GB is simply not enough nowadays. --- compiler-rt/lib/dfsan/dfsan_allocator.cpp | 2 +- compiler-rt/lib/lsan/lsan_allocator.cpp | 2 +- compiler-rt/lib/msan/msan_allocator.cpp | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/compiler-rt/lib/dfsan/dfsan_allocator.cpp b/compiler-rt/lib/dfsan/dfsan_allocator.cpp index 63475f434cd1..682df8c6e034 100644 --- a/compiler-rt/lib/dfsan/dfsan_allocator.cpp +++ b/compiler-rt/lib/dfsan/dfsan_allocator.cpp @@ -45,7 +45,7 @@ const uptr kAllocatorSpace = 0xE00000000000ULL; #else const uptr kAllocatorSpace = 0x700000000000ULL; #endif -const uptr kMaxAllowedMallocSize = 8UL << 30; +const uptr kMaxAllowedMallocSize = 1ULL << 40; struct AP64 { // Allocator64 parameters. Deliberately using a short name. static const uptr kSpaceBeg = kAllocatorSpace; diff --git a/compiler-rt/lib/lsan/lsan_allocator.cpp b/compiler-rt/lib/lsan/lsan_allocator.cpp index 12d579a9385b..493bf5f9efc5 100644 --- a/compiler-rt/lib/lsan/lsan_allocator.cpp +++ b/compiler-rt/lib/lsan/lsan_allocator.cpp @@ -31,7 +31,7 @@ static const uptr kMaxAllowedMallocSize = 1ULL << 30; #elif defined(__mips64) || defined(__aarch64__) static const uptr kMaxAllowedMallocSize = 4ULL << 30; #else -static const uptr kMaxAllowedMallocSize = 8ULL << 30; +static const uptr kMaxAllowedMallocSize = 1ULL << 40; #endif static Allocator allocator; diff --git a/compiler-rt/lib/msan/msan_allocator.cpp b/compiler-rt/lib/msan/msan_allocator.cpp index b1bc5b9390f7..8350106dc817 100644 --- a/compiler-rt/lib/msan/msan_allocator.cpp +++ b/compiler-rt/lib/msan/msan_allocator.cpp @@ -71,7 +71,7 @@ static const uptr kAllocatorSpace = 0x700000000000ULL; #else static const uptr kAllocatorSpace = 0x600000000000ULL; #endif -static const uptr kMaxAllowedMallocSize = 8UL << 30; +static const uptr kMaxAllowedMallocSize = 1ULL << 40; struct AP64 { // Allocator64 parameters. Deliberately using a short name. static const uptr kSpaceBeg = kAllocatorSpace; -- GitLab From a6d97dec899b880f0c3f674d6b3361a70b68ca09 Mon Sep 17 00:00:00 2001 From: Owen Pan Date: Tue, 21 May 2024 19:16:39 -0700 Subject: [PATCH 063/452] [clang-format] Correctly annotate C++ alternative operators in C (#92880) PR #90161 uncovered a bug that annotates C++ xor as UnaryOperator if followed by a binary operator. This patch fixes that and all other C++ alternative operator keywords when followed by a binary operator in C. Fixes #92688. --- clang/lib/Format/UnwrappedLineParser.cpp | 21 ++++++-- clang/unittests/Format/FormatTest.cpp | 2 + clang/unittests/Format/TokenAnnotatorTest.cpp | 54 +++++++++++++++++++ 3 files changed, 73 insertions(+), 4 deletions(-) diff --git a/clang/lib/Format/UnwrappedLineParser.cpp b/clang/lib/Format/UnwrappedLineParser.cpp index 3dd10f6bd2b3..b6f7567adc14 100644 --- a/clang/lib/Format/UnwrappedLineParser.cpp +++ b/clang/lib/Format/UnwrappedLineParser.cpp @@ -1410,6 +1410,13 @@ void UnwrappedLineParser::readTokenWithJavaScriptASI() { } } +static bool isAltOperator(const FormatToken &Tok) { + return isalpha(Tok.TokenText[0]) && + Tok.isOneOf(tok::ampamp, tok::ampequal, tok::amp, tok::pipe, + tok::tilde, tok::exclaim, tok::exclaimequal, tok::pipepipe, + tok::pipeequal, tok::caret, tok::caretequal); +} + void UnwrappedLineParser::parseStructuralElement( const FormatToken *OpeningBrace, IfStmtKind *IfKind, FormatToken **IfLeftBrace, bool *HasDoWhile, bool *HasLabel) { @@ -1689,9 +1696,15 @@ void UnwrappedLineParser::parseStructuralElement( break; } - const bool InRequiresExpression = - OpeningBrace && OpeningBrace->is(TT_RequiresExpressionLBrace); - do { + for (const bool InRequiresExpression = + OpeningBrace && OpeningBrace->is(TT_RequiresExpressionLBrace); + !eof();) { + if (IsCpp && isAltOperator(*FormatTok)) { + if (auto *Next = Tokens->peekNextToken(/*SkipComment=*/true); + Next && Next->isBinaryOperator()) { + FormatTok->Tok.setKind(tok::identifier); + } + } const FormatToken *Previous = FormatTok->Previous; switch (FormatTok->Tok.getKind()) { case tok::at: @@ -2122,7 +2135,7 @@ void UnwrappedLineParser::parseStructuralElement( nextToken(); break; } - } while (!eof()); + } } bool UnwrappedLineParser::tryToParsePropertyAccessor() { diff --git a/clang/unittests/Format/FormatTest.cpp b/clang/unittests/Format/FormatTest.cpp index 2f0c0f026677..a9df994189f0 100644 --- a/clang/unittests/Format/FormatTest.cpp +++ b/clang/unittests/Format/FormatTest.cpp @@ -17340,12 +17340,14 @@ TEST_F(FormatTest, ConfigurableSpaceBeforeAssignmentOperators) { verifyFormat("int a = 5;"); verifyFormat("a += 42;"); verifyFormat("a or_eq 8;"); + verifyFormat("xor = foo;"); FormatStyle Spaces = getLLVMStyle(); Spaces.SpaceBeforeAssignmentOperators = false; verifyFormat("int a= 5;", Spaces); verifyFormat("a+= 42;", Spaces); verifyFormat("a or_eq 8;", Spaces); + verifyFormat("xor= foo;", Spaces); } TEST_F(FormatTest, ConfigurableSpaceBeforeColon) { diff --git a/clang/unittests/Format/TokenAnnotatorTest.cpp b/clang/unittests/Format/TokenAnnotatorTest.cpp index 45c1554308c9..6ea9c4a241dc 100644 --- a/clang/unittests/Format/TokenAnnotatorTest.cpp +++ b/clang/unittests/Format/TokenAnnotatorTest.cpp @@ -3015,6 +3015,60 @@ TEST_F(TokenAnnotatorTest, SwitchExpression) { EXPECT_TOKEN(Tokens[20], tok::arrow, TT_CaseLabelArrow); } +TEST_F(TokenAnnotatorTest, CppAltOperatorKeywords) { + auto Tokens = annotate("a = b and c;"); + ASSERT_EQ(Tokens.size(), 7u); + EXPECT_TOKEN(Tokens[3], tok::ampamp, TT_BinaryOperator); + + Tokens = annotate("a = b and_eq c;"); + ASSERT_EQ(Tokens.size(), 7u); + EXPECT_TOKEN(Tokens[3], tok::ampequal, TT_BinaryOperator); + + Tokens = annotate("a = b bitand c;"); + ASSERT_EQ(Tokens.size(), 7u); + EXPECT_TOKEN(Tokens[3], tok::amp, TT_BinaryOperator); + + Tokens = annotate("a = b bitor c;"); + ASSERT_EQ(Tokens.size(), 7u); + EXPECT_TOKEN(Tokens[3], tok::pipe, TT_BinaryOperator); + + Tokens = annotate("a = b compl c;"); + ASSERT_EQ(Tokens.size(), 7u); + EXPECT_TOKEN(Tokens[3], tok::tilde, TT_UnaryOperator); + + Tokens = annotate("a = b not c;"); + ASSERT_EQ(Tokens.size(), 7u); + EXPECT_TOKEN(Tokens[3], tok::exclaim, TT_UnaryOperator); + + Tokens = annotate("a = b not_eq c;"); + ASSERT_EQ(Tokens.size(), 7u); + EXPECT_TOKEN(Tokens[3], tok::exclaimequal, TT_BinaryOperator); + + Tokens = annotate("a = b or c;"); + ASSERT_EQ(Tokens.size(), 7u); + EXPECT_TOKEN(Tokens[3], tok::pipepipe, TT_BinaryOperator); + + Tokens = annotate("a = b or_eq c;"); + ASSERT_EQ(Tokens.size(), 7u); + EXPECT_TOKEN(Tokens[3], tok::pipeequal, TT_BinaryOperator); + + Tokens = annotate("a = b xor c;"); + ASSERT_EQ(Tokens.size(), 7u); + EXPECT_TOKEN(Tokens[3], tok::caret, TT_BinaryOperator); + + Tokens = annotate("a = b xor_eq c;"); + ASSERT_EQ(Tokens.size(), 7u); + EXPECT_TOKEN(Tokens[3], tok::caretequal, TT_BinaryOperator); + + Tokens = annotate("xor = foo;"); + ASSERT_EQ(Tokens.size(), 5u); + EXPECT_TOKEN(Tokens[0], tok::identifier, TT_Unknown); + + Tokens = annotate("int xor = foo;"); + ASSERT_EQ(Tokens.size(), 6u); + EXPECT_TOKEN(Tokens[1], tok::identifier, TT_StartOfName); +} + } // namespace } // namespace format } // namespace clang -- GitLab From 935b946b1fdeeb9d67f1c42903dc15e88407208f Mon Sep 17 00:00:00 2001 From: Amir Ayupov Date: Tue, 21 May 2024 20:22:12 -0700 Subject: [PATCH 064/452] [BOLT] Process cross references between ignored functions in BAT mode (#92484) To align YAML and fdata profiles produced in BAT mode, lift two restrictions applied in non-relocation mode when BAT is present: 1) register secondary entry points from ignored functions, 2) treat functions with secondary entry points as simple. This allows constructing CFG for non-simple functions in non-relocation mode and emitting YAML profile for them, which can then be used for optimizations in relocation mode. Test Plan: added test ignored-interprocedural-reference.s --- bolt/include/bolt/Core/BinaryContext.h | 3 ++ bolt/lib/Core/BinaryContext.cpp | 4 +- bolt/lib/Core/BinaryFunction.cpp | 3 +- bolt/lib/Profile/YAMLProfileWriter.cpp | 4 ++ bolt/lib/Rewrite/RewriteInstance.cpp | 1 + .../X86/ignored-interprocedural-reference.s | 49 +++++++++++++++++++ 6 files changed, 62 insertions(+), 2 deletions(-) create mode 100644 bolt/test/X86/ignored-interprocedural-reference.s diff --git a/bolt/include/bolt/Core/BinaryContext.h b/bolt/include/bolt/Core/BinaryContext.h index 75765819ac46..edd0f7d2365a 100644 --- a/bolt/include/bolt/Core/BinaryContext.h +++ b/bolt/include/bolt/Core/BinaryContext.h @@ -677,6 +677,9 @@ public: /// have an origin file name available. bool HasSymbolsWithFileName{false}; + /// Does the binary have BAT section. + bool HasBATSection{false}; + /// Sum of execution count of all functions uint64_t SumExecutionCount{0}; diff --git a/bolt/lib/Core/BinaryContext.cpp b/bolt/lib/Core/BinaryContext.cpp index ad2eb18caf10..64d160adeee8 100644 --- a/bolt/lib/Core/BinaryContext.cpp +++ b/bolt/lib/Core/BinaryContext.cpp @@ -1322,7 +1322,9 @@ void BinaryContext::processInterproceduralReferences() { InterproceduralReferences) { BinaryFunction &Function = *It.first; uint64_t Address = It.second; - if (!Address || Function.isIgnored()) + // Process interprocedural references from ignored functions in BAT mode + // (non-simple in non-relocation mode) to properly register entry points + if (!Address || (Function.isIgnored() && !HasBATSection)) continue; BinaryFunction *TargetFunction = diff --git a/bolt/lib/Core/BinaryFunction.cpp b/bolt/lib/Core/BinaryFunction.cpp index 10b93e702984..1bb05f044fc8 100644 --- a/bolt/lib/Core/BinaryFunction.cpp +++ b/bolt/lib/Core/BinaryFunction.cpp @@ -1666,7 +1666,8 @@ void BinaryFunction::postProcessEntryPoints() { // In non-relocation mode there's potentially an external undetectable // reference to the entry point and hence we cannot move this entry // point. Optimizing without moving could be difficult. - if (!BC.HasRelocations) + // In BAT mode, register any known entry points for CFG construction. + if (!BC.HasRelocations && !BC.HasBATSection) setSimple(false); const uint32_t Offset = KV.first; diff --git a/bolt/lib/Profile/YAMLProfileWriter.cpp b/bolt/lib/Profile/YAMLProfileWriter.cpp index ef04ba0d21ad..89087155ebb4 100644 --- a/bolt/lib/Profile/YAMLProfileWriter.cpp +++ b/bolt/lib/Profile/YAMLProfileWriter.cpp @@ -39,6 +39,10 @@ const BinaryFunction *YAMLProfileWriter::setCSIDestination( BC.getFunctionForSymbol(Symbol, &EntryID)) { if (BAT && BAT->isBATFunction(Callee->getAddress())) std::tie(Callee, EntryID) = BAT->translateSymbol(BC, *Symbol, Offset); + else if (const BinaryBasicBlock *BB = + Callee->getBasicBlockContainingOffset(Offset)) + BC.getFunctionForSymbol(Callee->getSecondaryEntryPointSymbol(*BB), + &EntryID); CSI.DestId = Callee->getFunctionNumber(); CSI.EntryDiscriminator = EntryID; return Callee; diff --git a/bolt/lib/Rewrite/RewriteInstance.cpp b/bolt/lib/Rewrite/RewriteInstance.cpp index 6e1021a6df22..9cc4c8c8c4fa 100644 --- a/bolt/lib/Rewrite/RewriteInstance.cpp +++ b/bolt/lib/Rewrite/RewriteInstance.cpp @@ -1988,6 +1988,7 @@ Error RewriteInstance::readSpecialSections() { if (ErrorOr BATSec = BC->getUniqueSectionByName(BoltAddressTranslation::SECTION_NAME)) { + BC->HasBATSection = true; // Do not read BAT when plotting a heatmap if (!opts::HeatmapMode) { if (std::error_code EC = BAT->parse(BC->outs(), BATSec->getContents())) { diff --git a/bolt/test/X86/ignored-interprocedural-reference.s b/bolt/test/X86/ignored-interprocedural-reference.s new file mode 100644 index 000000000000..12e4fb92adcc --- /dev/null +++ b/bolt/test/X86/ignored-interprocedural-reference.s @@ -0,0 +1,49 @@ +# This reproduces a bug with not processing interprocedural references from +# ignored functions. + +# REQUIRES: system-linux + +# RUN: llvm-mc -filetype=obj -triple x86_64-unknown-unknown %s -o %t.o +# RUN: %clang %cflags %t.o -o %t.exe -nostdlib -Wl,-q +# RUN: llvm-bolt %t.exe -o %t.out --enable-bat -funcs=main +# RUN: link_fdata %s %t.out %t.preagg PREAGG +# RUN: perf2bolt %t.out -p %t.preagg --pa -o %t.fdata -w %t.yaml +# RUN: FileCheck %s --input-file=%t.fdata --check-prefix=CHECK-FDATA +# RUN: FileCheck %s --input-file=%t.yaml --check-prefix=CHECK-YAML + +# CHECK-FDATA: 1 main 0 1 foo a 1 1 +# CHECK-YAML: name: main +# CHECK-YAML: calls: {{.*}} disc: 1 + +# PREAGG: B #main# #foo_secondary# 1 1 +# main calls foo at valid instruction offset past nops that are to be stripped. + .globl main +main: + .cfi_startproc + call foo_secondary + ret + .cfi_endproc +.size main,.-main + +# Placeholder cold fragment to force main to be ignored in non-relocation mode. + .globl main.cold +main.cold: + .cfi_startproc + ud2 + .cfi_endproc +.size main.cold,.-main.cold + +# foo is set up to contain a valid instruction at called offset, and trapping +# instructions past that. + .globl foo +foo: + .cfi_startproc + .nops 10 + .globl foo_secondary +foo_secondary: + ret + .rept 20 + int3 + .endr + .cfi_endproc +.size foo,.-foo -- GitLab From 97025bd9d5b32f984f07d6ae20a3ce6ddb3fbe2a Mon Sep 17 00:00:00 2001 From: Amir Ayupov Date: Tue, 21 May 2024 20:24:46 -0700 Subject: [PATCH 065/452] [BOLT] Use getLocationName in YAMLProfileWriter (#92493) Disambiguate local functions using the containing file symbol in BAT mode. Make local function naming consistent across BAT fdata and YAML profiles. Test Plan: updated register-fragments-bolt-symbols.s --- bolt/include/bolt/Profile/DataAggregator.h | 5 ++++- bolt/lib/Profile/DataAggregator.cpp | 13 +++++++------ bolt/lib/Profile/YAMLProfileWriter.cpp | 3 ++- bolt/test/X86/register-fragments-bolt-symbols.s | 8 ++++++++ bolt/test/link_fdata.py | 3 +++ 5 files changed, 24 insertions(+), 8 deletions(-) diff --git a/bolt/include/bolt/Profile/DataAggregator.h b/bolt/include/bolt/Profile/DataAggregator.h index c158a9bb3e3f..6453b3070ceb 100644 --- a/bolt/include/bolt/Profile/DataAggregator.h +++ b/bolt/include/bolt/Profile/DataAggregator.h @@ -15,6 +15,7 @@ #define BOLT_PROFILE_DATA_AGGREGATOR_H #include "bolt/Profile/DataReader.h" +#include "bolt/Profile/YAMLProfileWriter.h" #include "llvm/ADT/StringRef.h" #include "llvm/Support/Error.h" #include "llvm/Support/Program.h" @@ -248,7 +249,7 @@ private: BinaryFunction *getBATParentFunction(const BinaryFunction &Func) const; /// Retrieve the location name to be used for samples recorded in \p Func. - StringRef getLocationName(const BinaryFunction &Func) const; + static StringRef getLocationName(const BinaryFunction &Func, bool BAT); /// Semantic actions - parser hooks to interpret parsed perf samples /// Register a sample (non-LBR mode), i.e. a new hit at \p Address @@ -490,6 +491,8 @@ public: /// Parse the output generated by "perf buildid-list" to extract build-ids /// and return a file name matching a given \p FileBuildID. std::optional getFileNameForBuildID(StringRef FileBuildID); + + friend class YAMLProfileWriter; }; } // namespace bolt } // namespace llvm diff --git a/bolt/lib/Profile/DataAggregator.cpp b/bolt/lib/Profile/DataAggregator.cpp index efda4932c09f..c0fd69b98c82 100644 --- a/bolt/lib/Profile/DataAggregator.cpp +++ b/bolt/lib/Profile/DataAggregator.cpp @@ -674,7 +674,8 @@ DataAggregator::getBATParentFunction(const BinaryFunction &Func) const { return nullptr; } -StringRef DataAggregator::getLocationName(const BinaryFunction &Func) const { +StringRef DataAggregator::getLocationName(const BinaryFunction &Func, + bool BAT) { if (!BAT) return Func.getOneName(); @@ -703,7 +704,7 @@ bool DataAggregator::doSample(BinaryFunction &OrigFunc, uint64_t Address, auto I = NamesToSamples.find(Func.getOneName()); if (I == NamesToSamples.end()) { bool Success; - StringRef LocName = getLocationName(Func); + StringRef LocName = getLocationName(Func, BAT); std::tie(I, Success) = NamesToSamples.insert( std::make_pair(Func.getOneName(), FuncSampleData(LocName, FuncSampleData::ContainerTy()))); @@ -723,7 +724,7 @@ bool DataAggregator::doIntraBranch(BinaryFunction &Func, uint64_t From, FuncBranchData *AggrData = getBranchData(Func); if (!AggrData) { AggrData = &NamesToBranches[Func.getOneName()]; - AggrData->Name = getLocationName(Func); + AggrData->Name = getLocationName(Func, BAT); setBranchData(Func, AggrData); } @@ -742,7 +743,7 @@ bool DataAggregator::doInterBranch(BinaryFunction *FromFunc, StringRef SrcFunc; StringRef DstFunc; if (FromFunc) { - SrcFunc = getLocationName(*FromFunc); + SrcFunc = getLocationName(*FromFunc, BAT); FromAggrData = getBranchData(*FromFunc); if (!FromAggrData) { FromAggrData = &NamesToBranches[FromFunc->getOneName()]; @@ -753,7 +754,7 @@ bool DataAggregator::doInterBranch(BinaryFunction *FromFunc, recordExit(*FromFunc, From, Mispreds, Count); } if (ToFunc) { - DstFunc = getLocationName(*ToFunc); + DstFunc = getLocationName(*ToFunc, BAT); ToAggrData = getBranchData(*ToFunc); if (!ToAggrData) { ToAggrData = &NamesToBranches[ToFunc->getOneName()]; @@ -2341,7 +2342,7 @@ std::error_code DataAggregator::writeBATYAML(BinaryContext &BC, continue; BinaryFunction *BF = BC.getBinaryFunctionAtAddress(FuncAddress); assert(BF); - YamlBF.Name = getLocationName(*BF); + YamlBF.Name = getLocationName(*BF, BAT); YamlBF.Id = BF->getFunctionNumber(); YamlBF.Hash = BAT->getBFHash(FuncAddress); YamlBF.ExecCount = BF->getKnownExecutionCount(); diff --git a/bolt/lib/Profile/YAMLProfileWriter.cpp b/bolt/lib/Profile/YAMLProfileWriter.cpp index 89087155ebb4..cf6b61ddd603 100644 --- a/bolt/lib/Profile/YAMLProfileWriter.cpp +++ b/bolt/lib/Profile/YAMLProfileWriter.cpp @@ -10,6 +10,7 @@ #include "bolt/Core/BinaryBasicBlock.h" #include "bolt/Core/BinaryFunction.h" #include "bolt/Profile/BoltAddressTranslation.h" +#include "bolt/Profile/DataAggregator.h" #include "bolt/Profile/ProfileReaderBase.h" #include "bolt/Rewrite/RewriteInstance.h" #include "llvm/Support/CommandLine.h" @@ -63,7 +64,7 @@ YAMLProfileWriter::convert(const BinaryFunction &BF, bool UseDFS, BF.computeHash(UseDFS); BF.computeBlockHashes(); - YamlBF.Name = BF.getPrintName(); + YamlBF.Name = DataAggregator::getLocationName(BF, BAT); YamlBF.Id = BF.getFunctionNumber(); YamlBF.Hash = BF.getHash(); YamlBF.NumBasicBlocks = BF.size(); diff --git a/bolt/test/X86/register-fragments-bolt-symbols.s b/bolt/test/X86/register-fragments-bolt-symbols.s index 6478adf19372..90c402b2234d 100644 --- a/bolt/test/X86/register-fragments-bolt-symbols.s +++ b/bolt/test/X86/register-fragments-bolt-symbols.s @@ -18,6 +18,11 @@ # RUN: FileCheck --input-file %t.bat.fdata --check-prefix=CHECK-FDATA %s # RUN: FileCheck --input-file %t.bat.yaml --check-prefix=CHECK-YAML %s +# RUN: link_fdata --no-redefine %s %t.bolt %t.preagg2 PREAGG2 +# PREAGG2: B X:0 #chain# 1 0 +# RUN: perf2bolt %t.bolt -p %t.preagg2 --pa -o %t.bat2.fdata -w %t.bat2.yaml +# RUN: FileCheck %s --input-file %t.bat2.yaml --check-prefix=CHECK-YAML2 + # CHECK-SYMS: l df *ABS* [[#]] chain.s # CHECK-SYMS: l F .bolt.org.text [[#]] chain # CHECK-SYMS: l F .text.cold [[#]] chain.cold.0 @@ -28,6 +33,9 @@ # CHECK-FDATA: 0 [unknown] 0 1 chain/chain.s/2 10 0 1 # CHECK-YAML: - name: 'chain/chain.s/2' +# CHECK-YAML2: - name: 'chain/chain.s/1' +## non-BAT function has non-zero insns: +# CHECK-YAML2: insns: 1 .file "chain.s" .text diff --git a/bolt/test/link_fdata.py b/bolt/test/link_fdata.py index 0232dd3211e9..3837e394ccc8 100755 --- a/bolt/test/link_fdata.py +++ b/bolt/test/link_fdata.py @@ -19,6 +19,7 @@ parser.add_argument("output") parser.add_argument("prefix", nargs="?", default="FDATA", help="Custom FDATA prefix") parser.add_argument("--nmtool", default="nm", help="Path to nm tool") parser.add_argument("--no-lbr", action="store_true") +parser.add_argument("--no-redefine", action="store_true") args = parser.parse_args() @@ -90,6 +91,8 @@ nm_output = subprocess.run( symbols = {} for symline in nm_output.splitlines(): symval, _, symname = symline.split(maxsplit=2) + if symname in symbols and args.no_redefine: + continue symbols[symname] = symval -- GitLab From 64f640680f7b1ddc8d2015eac75865f231166f8c Mon Sep 17 00:00:00 2001 From: Heejin Ahn Date: Tue, 21 May 2024 21:01:36 -0700 Subject: [PATCH 066/452] [WebAssembly] __USING_WASM_EXCEPTIONS__ -> __WASM_EXCEPTIONS__ (#92840) We've decided to change `__USING_WASM_EXCEPTIONS__` preprocessor to `__WASM_EXCEPTIONS__` given that it's more concise. --- libcxxabi/include/cxxabi.h | 2 +- libcxxabi/src/cxa_exception.cpp | 2 +- libcxxabi/src/cxa_exception.h | 2 +- libcxxabi/src/cxa_personality.cpp | 36 +++++++++++++++---------------- libunwind/src/Unwind-wasm.c | 4 ++-- libunwind/src/libunwind.cpp | 3 +-- 6 files changed, 24 insertions(+), 25 deletions(-) diff --git a/libcxxabi/include/cxxabi.h b/libcxxabi/include/cxxabi.h index d0701181751c..9d9beecf751f 100644 --- a/libcxxabi/include/cxxabi.h +++ b/libcxxabi/include/cxxabi.h @@ -53,7 +53,7 @@ __cxa_init_primary_exception(void* object, std::type_info* tinfo, void(_LIBCXXAB // 2.4.3 Throwing the Exception Object extern _LIBCXXABI_FUNC_VIS _LIBCXXABI_NORETURN void __cxa_throw(void *thrown_exception, std::type_info *tinfo, -#ifdef __USING_WASM_EXCEPTIONS__ +#ifdef __WASM_EXCEPTIONS__ // In Wasm, a destructor returns its argument void *(_LIBCXXABI_DTOR_FUNC *dest)(void *)); #else diff --git a/libcxxabi/src/cxa_exception.cpp b/libcxxabi/src/cxa_exception.cpp index 65e9f4504dda..3141d50a6bb9 100644 --- a/libcxxabi/src/cxa_exception.cpp +++ b/libcxxabi/src/cxa_exception.cpp @@ -267,7 +267,7 @@ will call terminate, assuming that there was no handler for the exception. */ void -#ifdef __USING_WASM_EXCEPTIONS__ +#ifdef __WASM_EXCEPTIONS__ // In Wasm, a destructor returns its argument __cxa_throw(void *thrown_object, std::type_info *tinfo, void *(_LIBCXXABI_DTOR_FUNC *dest)(void *)) { #else diff --git a/libcxxabi/src/cxa_exception.h b/libcxxabi/src/cxa_exception.h index 10712f6f47bb..7800b940b83f 100644 --- a/libcxxabi/src/cxa_exception.h +++ b/libcxxabi/src/cxa_exception.h @@ -43,7 +43,7 @@ struct _LIBCXXABI_HIDDEN __cxa_exception { // Manage the exception object itself. std::type_info *exceptionType; -#ifdef __USING_WASM_EXCEPTIONS__ +#ifdef __WASM_EXCEPTIONS__ // In Wasm, a destructor returns its argument void *(_LIBCXXABI_DTOR_FUNC *exceptionDestructor)(void *); #else diff --git a/libcxxabi/src/cxa_personality.cpp b/libcxxabi/src/cxa_personality.cpp index d95d78131940..843a18a4cbd8 100644 --- a/libcxxabi/src/cxa_personality.cpp +++ b/libcxxabi/src/cxa_personality.cpp @@ -70,7 +70,7 @@ extern "C" EXCEPTION_DISPOSITION _GCC_specific_handler(PEXCEPTION_RECORD, +------------------+--+-----+-----+------------------------+--------------------------+ | callSiteTableLength | (ULEB128) | Call Site Table length, used to find Action table | +---------------------+-----------+---------------------------------------------------+ -#if !defined(__USING_SJLJ_EXCEPTIONS__) && !defined(__USING_WASM_EXCEPTIONS__) +#if !defined(__USING_SJLJ_EXCEPTIONS__) && !defined(__WASM_EXCEPTIONS__) +---------------------+-----------+------------------------------------------------+ | Beginning of Call Site Table The current ip lies within the | | ... (start, length) range of one of these | @@ -84,7 +84,7 @@ extern "C" EXCEPTION_DISPOSITION _GCC_specific_handler(PEXCEPTION_RECORD, | +-------------+---------------------------------+------------------------------+ | | ... | +----------------------------------------------------------------------------------+ -#else // __USING_SJLJ_EXCEPTIONS__ || __USING_WASM_EXCEPTIONS__ +#else // __USING_SJLJ_EXCEPTIONS__ || __WASM_EXCEPTIONS__ +---------------------+-----------+------------------------------------------------+ | Beginning of Call Site Table The current ip is a 1-based index into | | ... this table. Or it is -1 meaning no | @@ -97,7 +97,7 @@ extern "C" EXCEPTION_DISPOSITION _GCC_specific_handler(PEXCEPTION_RECORD, | +-------------+---------------------------------+------------------------------+ | | ... | +----------------------------------------------------------------------------------+ -#endif // __USING_SJLJ_EXCEPTIONS__ || __USING_WASM_EXCEPTIONS__ +#endif // __USING_SJLJ_EXCEPTIONS__ || __WASM_EXCEPTIONS__ +---------------------------------------------------------------------+ | Beginning of Action Table ttypeIndex == 0 : cleanup | | ... ttypeIndex > 0 : catch | @@ -547,7 +547,7 @@ void set_registers(_Unwind_Exception* unwind_exception, _Unwind_Context* context, const scan_results& results) { -#if defined(__USING_SJLJ_EXCEPTIONS__) || defined(__USING_WASM_EXCEPTIONS__) +#if defined(__USING_SJLJ_EXCEPTIONS__) || defined(__WASM_EXCEPTIONS__) #define __builtin_eh_return_data_regno(regno) regno #elif defined(__ibmxl__) // IBM xlclang++ compiler does not support __builtin_eh_return_data_regno. @@ -642,7 +642,7 @@ static void scan_eh_tab(scan_results &results, _Unwind_Action actions, // Get beginning current frame's code (as defined by the // emitted dwarf code) uintptr_t funcStart = _Unwind_GetRegionStart(context); -#if defined(__USING_SJLJ_EXCEPTIONS__) || defined(__USING_WASM_EXCEPTIONS__) +#if defined(__USING_SJLJ_EXCEPTIONS__) || defined(__WASM_EXCEPTIONS__) if (ip == uintptr_t(-1)) { // no action @@ -652,9 +652,9 @@ static void scan_eh_tab(scan_results &results, _Unwind_Action actions, else if (ip == 0) call_terminate(native_exception, unwind_exception); // ip is 1-based index into call site table -#else // !__USING_SJLJ_EXCEPTIONS__ && !__USING_WASM_EXCEPTIONS__ +#else // !__USING_SJLJ_EXCEPTIONS__ && !__WASM_EXCEPTIONS__ uintptr_t ipOffset = ip - funcStart; -#endif // !__USING_SJLJ_EXCEPTIONS__ && !__USING_WASM_EXCEPTIONS__ +#endif // !__USING_SJLJ_EXCEPTIONS__ && !__WASM_EXCEPTIONS__ const uint8_t* classInfo = NULL; // Note: See JITDwarfEmitter::EmitExceptionTable(...) for corresponding // dwarf emission @@ -675,7 +675,7 @@ static void scan_eh_tab(scan_results &results, _Unwind_Action actions, // Walk call-site table looking for range that // includes current PC. uint8_t callSiteEncoding = *lsda++; -#if defined(__USING_SJLJ_EXCEPTIONS__) || defined(__USING_WASM_EXCEPTIONS__) +#if defined(__USING_SJLJ_EXCEPTIONS__) || defined(__WASM_EXCEPTIONS__) (void)callSiteEncoding; // When using SjLj/Wasm exceptions, callSiteEncoding is never used #endif uint32_t callSiteTableLength = static_cast(readULEB128(&lsda)); @@ -686,7 +686,7 @@ static void scan_eh_tab(scan_results &results, _Unwind_Action actions, while (callSitePtr < callSiteTableEnd) { // There is one entry per call site. -#if !defined(__USING_SJLJ_EXCEPTIONS__) && !defined(__USING_WASM_EXCEPTIONS__) +#if !defined(__USING_SJLJ_EXCEPTIONS__) && !defined(__WASM_EXCEPTIONS__) // The call sites are non-overlapping in [start, start+length) // The call sites are ordered in increasing value of start uintptr_t start = readEncodedPointer(&callSitePtr, callSiteEncoding); @@ -694,15 +694,15 @@ static void scan_eh_tab(scan_results &results, _Unwind_Action actions, uintptr_t landingPad = readEncodedPointer(&callSitePtr, callSiteEncoding); uintptr_t actionEntry = readULEB128(&callSitePtr); if ((start <= ipOffset) && (ipOffset < (start + length))) -#else // __USING_SJLJ_EXCEPTIONS__ || __USING_WASM_EXCEPTIONS__ +#else // __USING_SJLJ_EXCEPTIONS__ || __WASM_EXCEPTIONS__ // ip is 1-based index into this table uintptr_t landingPad = readULEB128(&callSitePtr); uintptr_t actionEntry = readULEB128(&callSitePtr); if (--ip == 0) -#endif // __USING_SJLJ_EXCEPTIONS__ || __USING_WASM_EXCEPTIONS__ +#endif // __USING_SJLJ_EXCEPTIONS__ || __WASM_EXCEPTIONS__ { // Found the call site containing ip. -#if !defined(__USING_SJLJ_EXCEPTIONS__) && !defined(__USING_WASM_EXCEPTIONS__) +#if !defined(__USING_SJLJ_EXCEPTIONS__) && !defined(__WASM_EXCEPTIONS__) if (landingPad == 0) { // No handler here @@ -710,9 +710,9 @@ static void scan_eh_tab(scan_results &results, _Unwind_Action actions, return; } landingPad = (uintptr_t)lpStart + landingPad; -#else // __USING_SJLJ_EXCEPTIONS__ || __USING_WASM_EXCEPTIONS__ +#else // __USING_SJLJ_EXCEPTIONS__ || __WASM_EXCEPTIONS__ ++landingPad; -#endif // __USING_SJLJ_EXCEPTIONS__ || __USING_WASM_EXCEPTIONS__ +#endif // __USING_SJLJ_EXCEPTIONS__ || __WASM_EXCEPTIONS__ results.landingPad = landingPad; if (actionEntry == 0) { @@ -838,7 +838,7 @@ static void scan_eh_tab(scan_results &results, _Unwind_Action actions, action += actionOffset; } // there is no break out of this loop, only return } -#if !defined(__USING_SJLJ_EXCEPTIONS__) && !defined(__USING_WASM_EXCEPTIONS__) +#if !defined(__USING_SJLJ_EXCEPTIONS__) && !defined(__WASM_EXCEPTIONS__) else if (ipOffset < start) { // There is no call site for this ip @@ -846,7 +846,7 @@ static void scan_eh_tab(scan_results &results, _Unwind_Action actions, // Possible stack corruption. call_terminate(native_exception, unwind_exception); } -#endif // !__USING_SJLJ_EXCEPTIONS__ && !__USING_WASM_EXCEPTIONS__ +#endif // !__USING_SJLJ_EXCEPTIONS__ && !__WASM_EXCEPTIONS__ } // there might be some tricky cases which break out of this loop // It is possible that no eh table entry specify how to handle @@ -903,7 +903,7 @@ _UA_CLEANUP_PHASE */ #if !defined(_LIBCXXABI_ARM_EHABI) -#ifdef __USING_WASM_EXCEPTIONS__ +#ifdef __WASM_EXCEPTIONS__ _Unwind_Reason_Code __gxx_personality_wasm0 #elif defined(__SEH__) && !defined(__USING_SJLJ_EXCEPTIONS__) static _Unwind_Reason_Code __gxx_personality_imp @@ -972,7 +972,7 @@ __gxx_personality_v0 exc->languageSpecificData = results.languageSpecificData; exc->catchTemp = reinterpret_cast(results.landingPad); exc->adjustedPtr = results.adjustedPtr; -#ifdef __USING_WASM_EXCEPTIONS__ +#ifdef __WASM_EXCEPTIONS__ // Wasm only uses a single phase (_UA_SEARCH_PHASE), so save the // results here. set_registers(unwind_exception, context, results); diff --git a/libunwind/src/Unwind-wasm.c b/libunwind/src/Unwind-wasm.c index f7f39d38b59c..b18b32c5d178 100644 --- a/libunwind/src/Unwind-wasm.c +++ b/libunwind/src/Unwind-wasm.c @@ -14,7 +14,7 @@ #include "config.h" -#ifdef __USING_WASM_EXCEPTIONS__ +#ifdef __WASM_EXCEPTIONS__ #include "unwind.h" #include @@ -120,4 +120,4 @@ _Unwind_GetRegionStart(struct _Unwind_Context *context) { return 0; } -#endif // defined(__USING_WASM_EXCEPTIONS__) +#endif // defined(__WASM_EXCEPTIONS__) diff --git a/libunwind/src/libunwind.cpp b/libunwind/src/libunwind.cpp index 7e5c6bd263e1..cf39ec5f7dbd 100644 --- a/libunwind/src/libunwind.cpp +++ b/libunwind/src/libunwind.cpp @@ -347,8 +347,7 @@ void __unw_remove_dynamic_eh_frame_section(unw_word_t eh_frame_start) { } #endif // defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) -#endif // !defined(__USING_SJLJ_EXCEPTIONS__) && - // !defined(__wasm__) +#endif // !defined(__USING_SJLJ_EXCEPTIONS__) && !defined(__wasm__) #ifdef __APPLE__ -- GitLab From d53c6cdbc108729ce5dc7d4e9184db025206fefc Mon Sep 17 00:00:00 2001 From: Shilei Tian Date: Wed, 22 May 2024 00:03:59 -0400 Subject: [PATCH 067/452] [AMDGPU][Clang] Builtin for GLOBAL_LOAD_LDS on GFX940 (#92962) Fixes: SWDEV-459212 --- clang/include/clang/Basic/BuiltinsAMDGPU.def | 1 + .../CodeGenOpenCL/builtins-amdgcn-gfx940.cl | 52 +++++++++++++++++++ llvm/include/llvm/IR/IntrinsicsAMDGPU.td | 31 +++++------ 3 files changed, 67 insertions(+), 17 deletions(-) create mode 100644 clang/test/CodeGenOpenCL/builtins-amdgcn-gfx940.cl diff --git a/clang/include/clang/Basic/BuiltinsAMDGPU.def b/clang/include/clang/Basic/BuiltinsAMDGPU.def index 3e21a2fe2ac6..efa652eee990 100644 --- a/clang/include/clang/Basic/BuiltinsAMDGPU.def +++ b/clang/include/clang/Basic/BuiltinsAMDGPU.def @@ -240,6 +240,7 @@ TARGET_BUILTIN(__builtin_amdgcn_flat_atomic_fadd_v2bf16, "V2sV2s*0V2s", "t", "at TARGET_BUILTIN(__builtin_amdgcn_global_atomic_fadd_v2bf16, "V2sV2s*1V2s", "t", "atomic-global-pk-add-bf16-inst") TARGET_BUILTIN(__builtin_amdgcn_ds_atomic_fadd_v2bf16, "V2sV2s*3V2s", "t", "atomic-ds-pk-add-16-insts") TARGET_BUILTIN(__builtin_amdgcn_ds_atomic_fadd_v2f16, "V2hV2h*3V2h", "t", "atomic-ds-pk-add-16-insts") +TARGET_BUILTIN(__builtin_amdgcn_global_load_lds, "vv*1v*3UiiUi", "t", "gfx940-insts") //===----------------------------------------------------------------------===// // Deep learning builtins. diff --git a/clang/test/CodeGenOpenCL/builtins-amdgcn-gfx940.cl b/clang/test/CodeGenOpenCL/builtins-amdgcn-gfx940.cl new file mode 100644 index 000000000000..fc5649d8a41f --- /dev/null +++ b/clang/test/CodeGenOpenCL/builtins-amdgcn-gfx940.cl @@ -0,0 +1,52 @@ +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py +// RUN: %clang_cc1 -cl-std=CL2.0 -O0 -triple amdgcn-unknown-unknown -target-cpu gfx940 -emit-llvm -o - %s | FileCheck %s +// REQUIRES: amdgpu-registered-target + +typedef unsigned int u32; +typedef unsigned short u16; +typedef unsigned char u8; + +// CHECK-LABEL: @test_global_load_lds_u32( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[SRC_ADDR:%.*]] = alloca ptr addrspace(1), align 8, addrspace(5) +// CHECK-NEXT: [[DST_ADDR:%.*]] = alloca ptr addrspace(3), align 4, addrspace(5) +// CHECK-NEXT: store ptr addrspace(1) [[SRC:%.*]], ptr addrspace(5) [[SRC_ADDR]], align 8 +// CHECK-NEXT: store ptr addrspace(3) [[DST:%.*]], ptr addrspace(5) [[DST_ADDR]], align 4 +// CHECK-NEXT: [[TMP0:%.*]] = load ptr addrspace(1), ptr addrspace(5) [[SRC_ADDR]], align 8 +// CHECK-NEXT: [[TMP1:%.*]] = load ptr addrspace(3), ptr addrspace(5) [[DST_ADDR]], align 4 +// CHECK-NEXT: call void @llvm.amdgcn.global.load.lds(ptr addrspace(1) [[TMP0]], ptr addrspace(3) [[TMP1]], i32 4, i32 0, i32 0) +// CHECK-NEXT: ret void +// +void test_global_load_lds_u32(global u32* src, local u32 *dst) { + __builtin_amdgcn_global_load_lds(src, dst, /*size=*/4, /*offset=*/0, /*aux=*/0); +} + +// CHECK-LABEL: @test_global_load_lds_u16( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[SRC_ADDR:%.*]] = alloca ptr addrspace(1), align 8, addrspace(5) +// CHECK-NEXT: [[DST_ADDR:%.*]] = alloca ptr addrspace(3), align 4, addrspace(5) +// CHECK-NEXT: store ptr addrspace(1) [[SRC:%.*]], ptr addrspace(5) [[SRC_ADDR]], align 8 +// CHECK-NEXT: store ptr addrspace(3) [[DST:%.*]], ptr addrspace(5) [[DST_ADDR]], align 4 +// CHECK-NEXT: [[TMP0:%.*]] = load ptr addrspace(1), ptr addrspace(5) [[SRC_ADDR]], align 8 +// CHECK-NEXT: [[TMP1:%.*]] = load ptr addrspace(3), ptr addrspace(5) [[DST_ADDR]], align 4 +// CHECK-NEXT: call void @llvm.amdgcn.global.load.lds(ptr addrspace(1) [[TMP0]], ptr addrspace(3) [[TMP1]], i32 2, i32 0, i32 0) +// CHECK-NEXT: ret void +// +void test_global_load_lds_u16(global u16* src, local u16 *dst) { + __builtin_amdgcn_global_load_lds(src, dst, /*size=*/2, /*offset=*/0, /*aux=*/0); +} + +// CHECK-LABEL: @test_global_load_lds_u8( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[SRC_ADDR:%.*]] = alloca ptr addrspace(1), align 8, addrspace(5) +// CHECK-NEXT: [[DST_ADDR:%.*]] = alloca ptr addrspace(3), align 4, addrspace(5) +// CHECK-NEXT: store ptr addrspace(1) [[SRC:%.*]], ptr addrspace(5) [[SRC_ADDR]], align 8 +// CHECK-NEXT: store ptr addrspace(3) [[DST:%.*]], ptr addrspace(5) [[DST_ADDR]], align 4 +// CHECK-NEXT: [[TMP0:%.*]] = load ptr addrspace(1), ptr addrspace(5) [[SRC_ADDR]], align 8 +// CHECK-NEXT: [[TMP1:%.*]] = load ptr addrspace(3), ptr addrspace(5) [[DST_ADDR]], align 4 +// CHECK-NEXT: call void @llvm.amdgcn.global.load.lds(ptr addrspace(1) [[TMP0]], ptr addrspace(3) [[TMP1]], i32 1, i32 0, i32 0) +// CHECK-NEXT: ret void +// +void test_global_load_lds_u8(global u8* src, local u8 *dst) { + __builtin_amdgcn_global_load_lds(src, dst, /*size=*/1, /*offset=*/0, /*aux=*/0); +} diff --git a/llvm/include/llvm/IR/IntrinsicsAMDGPU.td b/llvm/include/llvm/IR/IntrinsicsAMDGPU.td index be8048ca2459..0b774b724d0c 100644 --- a/llvm/include/llvm/IR/IntrinsicsAMDGPU.td +++ b/llvm/include/llvm/IR/IntrinsicsAMDGPU.td @@ -2466,23 +2466,20 @@ def int_amdgcn_perm : // GFX9 Intrinsics //===----------------------------------------------------------------------===// -class AMDGPUGlobalLoadLDS : Intrinsic < - [], - [LLVMQualPointerType<1>, // Base global pointer to load from - LLVMQualPointerType<3>, // LDS base pointer to store to - llvm_i32_ty, // Data byte size: 1/2/4 - llvm_i32_ty, // imm offset (applied to both global and LDS address) - llvm_i32_ty], // auxiliary data (imm, cachepolicy (bit 0 = glc/sc0, - // bit 1 = slc/sc1, - // bit 2 = dlc on gfx10/gfx11)) - // bit 4 = scc/nt on gfx90a+)) - // gfx12+: - // cachepolicy (bits [0-2] = th, - // bits [3-4] = scope) - // swizzled buffer (bit 6 = swz), - [IntrWillReturn, NoCapture>, NoCapture>, - ImmArg>, ImmArg>, ImmArg>, IntrNoCallback, IntrNoFree], - "", [SDNPMemOperand]>; +class AMDGPUGlobalLoadLDS : + ClangBuiltin<"__builtin_amdgcn_global_load_lds">, + Intrinsic < + [], + [LLVMQualPointerType<1>, // Base global pointer to load from + LLVMQualPointerType<3>, // LDS base pointer to store to + llvm_i32_ty, // Data byte size: 1/2/4 (/12/16 for gfx950) + llvm_i32_ty, // imm offset (applied to both global and LDS address) + llvm_i32_ty], // auxiliary data (imm, cachepolicy (bit 0 = sc0, + // bit 1 = sc1, + // bit 4 = scc)) + [IntrWillReturn, NoCapture>, NoCapture>, + ImmArg>, ImmArg>, ImmArg>, IntrNoCallback, IntrNoFree], + "", [SDNPMemOperand]>; def int_amdgcn_global_load_lds : AMDGPUGlobalLoadLDS; //===----------------------------------------------------------------------===// -- GitLab From b66779b5bf0f3c839114681bb4aca80a9dc144c3 Mon Sep 17 00:00:00 2001 From: Mingming Liu Date: Tue, 21 May 2024 21:25:12 -0700 Subject: [PATCH 068/452] [nfc][InstrProfReader]Store header fields in native endianness (#92947) - Use `Header.Version` directly and remove Header::formatVersion --------- Co-authored-by: Kazu Hirata --- llvm/include/llvm/ProfileData/InstrProf.h | 7 +--- llvm/lib/ProfileData/InstrProf.cpp | 22 ++++------ llvm/lib/ProfileData/InstrProfReader.cpp | 50 ++++++++--------------- 3 files changed, 28 insertions(+), 51 deletions(-) diff --git a/llvm/include/llvm/ProfileData/InstrProf.h b/llvm/include/llvm/ProfileData/InstrProf.h index 88c7fe425b5a..a57f9e1b7b4a 100644 --- a/llvm/include/llvm/ProfileData/InstrProf.h +++ b/llvm/include/llvm/ProfileData/InstrProf.h @@ -1203,16 +1203,13 @@ struct Header { // computation is correct. The methods below need to be updated to ensure that // the new field is read correctly. - // Reads a header struct from the buffer. + // Reads a header struct from the buffer. Header fields are in machine native + // endianness. static Expected
readFromBuffer(const unsigned char *Buffer); // Returns the size of the header in bytes for all valid fields based on the // version. I.e a older version header will return a smaller size. size_t size() const; - - // Returns the format version in little endian. The header retains the version - // in native endian of the compiler runtime. - uint64_t formatVersion() const; }; // Profile summary data recorded in the profile data file in indexed diff --git a/llvm/lib/ProfileData/InstrProf.cpp b/llvm/lib/ProfileData/InstrProf.cpp index 806d01de1ada..04dd7bac029e 100644 --- a/llvm/lib/ProfileData/InstrProf.cpp +++ b/llvm/lib/ProfileData/InstrProf.cpp @@ -1620,13 +1620,12 @@ inline size_t constexpr offsetOf(T1 T2::*Member) { return size_t(&(Object.*Member)) - size_t(&Object); } +// Read a uint64_t from the specified buffer offset, and swap the bytes in +// native endianness if necessary. static inline uint64_t read(const unsigned char *Buffer, size_t Offset) { - return *reinterpret_cast(Buffer + Offset); -} - -uint64_t Header::formatVersion() const { - using namespace support; - return endian::byte_swap(Version); + using namespace ::support; + return endian::read(Buffer + + Offset); } Expected
Header::readFromBuffer(const unsigned char *Buffer) { @@ -1638,18 +1637,15 @@ Expected
Header::readFromBuffer(const unsigned char *Buffer) { H.Magic = read(Buffer, offsetOf(&Header::Magic)); // Check the magic number. - uint64_t Magic = - endian::byte_swap(H.Magic); - if (Magic != IndexedInstrProf::Magic) + if (H.Magic != IndexedInstrProf::Magic) return make_error(instrprof_error::bad_magic); // Read the version. H.Version = read(Buffer, offsetOf(&Header::Version)); - if (GET_VERSION(H.formatVersion()) > - IndexedInstrProf::ProfVersion::CurrentVersion) + if (GET_VERSION(H.Version) > IndexedInstrProf::ProfVersion::CurrentVersion) return make_error(instrprof_error::unsupported_version); - switch (GET_VERSION(H.formatVersion())) { + switch (GET_VERSION(H.Version)) { // When a new field is added in the header add a case statement here to // populate it. static_assert( @@ -1680,7 +1676,7 @@ Expected
Header::readFromBuffer(const unsigned char *Buffer) { } size_t Header::size() const { - switch (GET_VERSION(formatVersion())) { + switch (GET_VERSION(Version)) { // When a new field is added to the header add a case statement here to // compute the size as offset of the new field + size of the new field. This // relies on the field being added to the end of the list. diff --git a/llvm/lib/ProfileData/InstrProfReader.cpp b/llvm/lib/ProfileData/InstrProfReader.cpp index ba21e01abfba..2a87a386ea67 100644 --- a/llvm/lib/ProfileData/InstrProfReader.cpp +++ b/llvm/lib/ProfileData/InstrProfReader.cpp @@ -1311,43 +1311,33 @@ Error IndexedInstrProfReader::readHeader() { const IndexedInstrProf::Header *Header = &HeaderOr.get(); Cur += Header->size(); - Cur = readSummary((IndexedInstrProf::ProfVersion)Header->formatVersion(), Cur, + Cur = readSummary((IndexedInstrProf::ProfVersion)Header->Version, Cur, /* UseCS */ false); - if (Header->formatVersion() & VARIANT_MASK_CSIR_PROF) - Cur = - readSummary((IndexedInstrProf::ProfVersion)Header->formatVersion(), Cur, - /* UseCS */ true); + if (Header->Version & VARIANT_MASK_CSIR_PROF) + Cur = readSummary((IndexedInstrProf::ProfVersion)Header->Version, Cur, + /* UseCS */ true); // Read the hash type and start offset. - IndexedInstrProf::HashT HashType = static_cast( - endian::byte_swap(Header->HashType)); + IndexedInstrProf::HashT HashType = + static_cast(Header->HashType); if (HashType > IndexedInstrProf::HashT::Last) return error(instrprof_error::unsupported_hash_type); - uint64_t HashOffset = - endian::byte_swap(Header->HashOffset); - // The hash table with profile counts comes next. auto IndexPtr = std::make_unique>( - Start + HashOffset, Cur, Start, HashType, Header->formatVersion()); + Start + Header->HashOffset, Cur, Start, HashType, Header->Version); // The MemProfOffset field in the header is only valid when the format // version is higher than 8 (when it was introduced). - if (GET_VERSION(Header->formatVersion()) >= 8 && - Header->formatVersion() & VARIANT_MASK_MEMPROF) { - uint64_t MemProfOffset = - endian::byte_swap( - Header->MemProfOffset); - if (Error E = MemProfReader.deserialize(Start, MemProfOffset)) + if (GET_VERSION(Header->Version) >= 8 && + Header->Version & VARIANT_MASK_MEMPROF) { + if (Error E = MemProfReader.deserialize(Start, Header->MemProfOffset)) return E; } // BinaryIdOffset field in the header is only valid when the format version // is higher than 9 (when it was introduced). - if (GET_VERSION(Header->formatVersion()) >= 9) { - uint64_t BinaryIdOffset = - endian::byte_swap( - Header->BinaryIdOffset); - const unsigned char *Ptr = Start + BinaryIdOffset; + if (GET_VERSION(Header->Version) >= 9) { + const unsigned char *Ptr = Start + Header->BinaryIdOffset; // Read binary ids size. BinaryIdsSize = support::endian::readNext(Ptr); @@ -1360,11 +1350,8 @@ Error IndexedInstrProfReader::readHeader() { "corrupted binary ids"); } - if (GET_VERSION(Header->formatVersion()) >= 12) { - uint64_t VTableNamesOffset = - endian::byte_swap( - Header->VTableNamesOffset); - const unsigned char *Ptr = Start + VTableNamesOffset; + if (GET_VERSION(Header->Version) >= 12) { + const unsigned char *Ptr = Start + Header->VTableNamesOffset; CompressedVTableNamesLen = support::endian::readNext(Ptr); @@ -1376,12 +1363,9 @@ Error IndexedInstrProfReader::readHeader() { return make_error(instrprof_error::truncated); } - if (GET_VERSION(Header->formatVersion()) >= 10 && - Header->formatVersion() & VARIANT_MASK_TEMPORAL_PROF) { - uint64_t TemporalProfTracesOffset = - endian::byte_swap( - Header->TemporalProfTracesOffset); - const unsigned char *Ptr = Start + TemporalProfTracesOffset; + if (GET_VERSION(Header->Version) >= 10 && + Header->Version & VARIANT_MASK_TEMPORAL_PROF) { + const unsigned char *Ptr = Start + Header->TemporalProfTracesOffset; const auto *PtrEnd = (const unsigned char *)DataBuffer->getBufferEnd(); // Expect at least two 64 bit fields: NumTraces, and TraceStreamSize if (Ptr + 2 * sizeof(uint64_t) > PtrEnd) -- GitLab From 130e93cc26ca9d3ac50ec5a92e3109577ca2e702 Mon Sep 17 00:00:00 2001 From: Pengcheng Wang Date: Wed, 22 May 2024 12:37:27 +0800 Subject: [PATCH 069/452] Reland "[clang] Enable sized deallocation by default in C++14 onwards" (#90373) Since C++14 has been released for about nine years and most standard libraries have implemented sized deallocation functions, it's time to make this feature default again. This is another try of https://reviews.llvm.org/D112921. The original commit cf5a8b4 was reverted by 2e5035a due to some failures (see #83774). Fixes #60061 --- .../clangd/unittests/FindTargetTests.cpp | 4 +- .../checkers/misc/new-delete-overloads.cpp | 10 - clang/docs/ReleaseNotes.rst | 5 + clang/include/clang/Driver/Options.td | 8 +- clang/lib/Driver/ToolChains/Clang.cpp | 13 +- clang/lib/Driver/ToolChains/Darwin.cpp | 58 ++++- clang/lib/Driver/ToolChains/Darwin.h | 4 + clang/lib/Driver/ToolChains/ZOS.cpp | 6 + clang/test/AST/ast-dump-expr-json.cpp | 2 +- clang/test/AST/ast-dump-expr.cpp | 2 +- clang/test/AST/ast-dump-stmt-json.cpp | 244 +++++++++++++++++- clang/test/Analysis/cxxnewexpr-callback.cpp | 4 +- .../basic.stc.dynamic.deallocation/p2.cpp | 2 +- clang/test/CXX/drs/cwg292.cpp | 17 +- .../test/CXX/expr/expr.unary/expr.new/p14.cpp | 2 +- .../CodeGenCXX/cxx1y-sized-deallocation.cpp | 10 +- .../CodeGenCXX/cxx1z-aligned-allocation.cpp | 6 +- .../CodeGenCXX/cxx2a-destroying-delete.cpp | 4 +- clang/test/CodeGenCXX/delete-two-arg.cpp | 4 +- clang/test/CodeGenCXX/delete.cpp | 12 +- clang/test/CodeGenCXX/dllimport.cpp | 4 +- clang/test/CodeGenCXX/new.cpp | 6 +- .../coro-aligned-alloc-2.cpp | 2 - .../CodeGenCoroutines/coro-aligned-alloc.cpp | 6 +- clang/test/CodeGenCoroutines/coro-alloc.cpp | 6 +- clang/test/CodeGenCoroutines/coro-cleanup.cpp | 6 +- clang/test/CodeGenCoroutines/coro-dealloc.cpp | 2 - clang/test/CodeGenCoroutines/coro-gro.cpp | 3 +- clang/test/CodeGenCoroutines/pr56919.cpp | 9 +- clang/test/Lexer/cxx-features.cpp | 20 +- clang/test/PCH/cxx1z-aligned-alloc.cpp | 10 +- clang/test/SemaCXX/MicrosoftExtensions.cpp | 8 +- .../SemaCXX/builtin-operator-new-delete.cpp | 2 +- .../test/SemaCXX/cxx1y-sized-deallocation.cpp | 2 +- .../unavailable_aligned_allocation.cpp | 15 +- clang/tools/clang-repl/CMakeLists.txt | 43 +++ clang/unittests/Interpreter/CMakeLists.txt | 43 +++ .../StaticAnalyzer/CallEventTest.cpp | 2 +- clang/www/cxx_status.html | 11 +- .../support.dynamic/libcpp_deallocate.sh.cpp | 3 + .../sized_delete_array14.pass.cpp | 8 +- .../new.delete.single/sized_delete14.pass.cpp | 8 +- 42 files changed, 523 insertions(+), 113 deletions(-) diff --git a/clang-tools-extra/clangd/unittests/FindTargetTests.cpp b/clang-tools-extra/clangd/unittests/FindTargetTests.cpp index 0b2273f0a9a6..3220a5a6a982 100644 --- a/clang-tools-extra/clangd/unittests/FindTargetTests.cpp +++ b/clang-tools-extra/clangd/unittests/FindTargetTests.cpp @@ -836,7 +836,9 @@ TEST_F(TargetDeclTest, OverloadExpr) { [[delete]] x; } )cpp"; - EXPECT_DECLS("CXXDeleteExpr", "void operator delete(void *) noexcept"); + // Sized deallocation is enabled by default in C++14 onwards. + EXPECT_DECLS("CXXDeleteExpr", + "void operator delete(void *, unsigned long) noexcept"); } TEST_F(TargetDeclTest, DependentExprs) { diff --git a/clang-tools-extra/test/clang-tidy/checkers/misc/new-delete-overloads.cpp b/clang-tools-extra/test/clang-tidy/checkers/misc/new-delete-overloads.cpp index 78f021144b2e..f86fe8a4c5b1 100644 --- a/clang-tools-extra/test/clang-tidy/checkers/misc/new-delete-overloads.cpp +++ b/clang-tools-extra/test/clang-tidy/checkers/misc/new-delete-overloads.cpp @@ -12,16 +12,6 @@ struct S { // CHECK-MESSAGES: :[[@LINE+1]]:7: warning: declaration of 'operator new' has no matching declaration of 'operator delete' at the same scope void *operator new(size_t size) noexcept(false); -struct T { - // Sized deallocations are not enabled by default, and so this new/delete pair - // does not match. However, we expect only one warning, for the new, because - // the operator delete is a placement delete and we do not warn on mismatching - // placement operations. - // CHECK-MESSAGES: :[[@LINE+1]]:9: warning: declaration of 'operator new' has no matching declaration of 'operator delete' at the same scope - void *operator new(size_t size) noexcept; - void operator delete(void *ptr, size_t) noexcept; // ok only if sized deallocation is enabled -}; - struct U { void *operator new(size_t size) noexcept; void operator delete(void *ptr) noexcept; diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 81e9d0423f96..2899bc5ed35a 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -155,6 +155,11 @@ C++17 Feature Support files because they may not be stable across multiple TUs (the values may vary based on compiler version as well as CPU tuning). #GH60174 +C++14 Feature Support +^^^^^^^^^^^^^^^^^^^^^ +- Sized deallocation is enabled by default in C++14 onwards. The user may specify + ``-fno-sized-deallocation`` to disable it if there are some regressions. + C++20 Feature Support ^^^^^^^^^^^^^^^^^^^^^ diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td index 7bb781667e92..8cbb7f854ee7 100644 --- a/clang/include/clang/Driver/Options.td +++ b/clang/include/clang/Driver/Options.td @@ -603,6 +603,7 @@ class MarshallingInfoVisibility // Key paths that are constant during parsing of options with the same key path prefix. defvar cplusplus = LangOpts<"CPlusPlus">; defvar cpp11 = LangOpts<"CPlusPlus11">; +defvar cpp14 = LangOpts<"CPlusPlus14">; defvar cpp17 = LangOpts<"CPlusPlus17">; defvar cpp20 = LangOpts<"CPlusPlus20">; defvar c99 = LangOpts<"C99">; @@ -3388,10 +3389,9 @@ defm relaxed_template_template_args : BoolFOption<"relaxed-template-template-arg NegFlag, BothFlags<[], [ClangOption], " C++17 relaxed template template argument matching">>; defm sized_deallocation : BoolFOption<"sized-deallocation", - LangOpts<"SizedDeallocation">, DefaultFalse, - PosFlag, - NegFlag>; + LangOpts<"SizedDeallocation">, Default, + PosFlag, + NegFlag, BothFlags<[], [ClangOption, CC1Option]>>; defm aligned_allocation : BoolFOption<"aligned-allocation", LangOpts<"AlignedAllocation">, Default, PosFlag, diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp index 6d2015b2cd15..588f0c511cd2 100644 --- a/clang/lib/Driver/ToolChains/Clang.cpp +++ b/clang/lib/Driver/ToolChains/Clang.cpp @@ -7263,10 +7263,15 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, } } - // -fsized-deallocation is off by default, as it is an ABI-breaking change for - // most platforms. - Args.addOptInFlag(CmdArgs, options::OPT_fsized_deallocation, - options::OPT_fno_sized_deallocation); + // -fsized-deallocation is on by default in C++14 onwards and otherwise off + // by default. + if (Arg *A = Args.getLastArg(options::OPT_fsized_deallocation, + options::OPT_fno_sized_deallocation)) { + if (A->getOption().matches(options::OPT_fno_sized_deallocation)) + CmdArgs.push_back("-fno-sized-deallocation"); + else + CmdArgs.push_back("-fsized-deallocation"); + } // -faligned-allocation is on by default in C++17 onwards and otherwise off // by default. diff --git a/clang/lib/Driver/ToolChains/Darwin.cpp b/clang/lib/Driver/ToolChains/Darwin.cpp index caf6c4a444fd..593b403a1e3f 100644 --- a/clang/lib/Driver/ToolChains/Darwin.cpp +++ b/clang/lib/Driver/ToolChains/Darwin.cpp @@ -2912,9 +2912,54 @@ static bool sdkSupportsBuiltinModules(const Darwin::DarwinPlatformKind &TargetPl } } -void Darwin::addClangTargetOptions(const llvm::opt::ArgList &DriverArgs, - llvm::opt::ArgStringList &CC1Args, - Action::OffloadKind DeviceOffloadKind) const { +static inline llvm::VersionTuple +sizedDeallocMinVersion(llvm::Triple::OSType OS) { + switch (OS) { + default: + break; + case llvm::Triple::Darwin: + case llvm::Triple::MacOSX: // Earliest supporting version is 10.12. + return llvm::VersionTuple(10U, 12U); + case llvm::Triple::IOS: + case llvm::Triple::TvOS: // Earliest supporting version is 10.0.0. + return llvm::VersionTuple(10U); + case llvm::Triple::WatchOS: // Earliest supporting version is 3.0.0. + return llvm::VersionTuple(3U); + } + + llvm_unreachable("Unexpected OS"); +} + +bool Darwin::isSizedDeallocationUnavailable() const { + llvm::Triple::OSType OS; + + if (isTargetMacCatalyst()) + return TargetVersion < sizedDeallocMinVersion(llvm::Triple::MacOSX); + switch (TargetPlatform) { + case MacOS: // Earlier than 10.12. + OS = llvm::Triple::MacOSX; + break; + case IPhoneOS: + OS = llvm::Triple::IOS; + break; + case TvOS: // Earlier than 10.0. + OS = llvm::Triple::TvOS; + break; + case WatchOS: // Earlier than 3.0. + OS = llvm::Triple::WatchOS; + break; + case DriverKit: + case XROS: + // Always available. + return false; + } + + return TargetVersion < sizedDeallocMinVersion(OS); +} + +void Darwin::addClangTargetOptions( + const llvm::opt::ArgList &DriverArgs, llvm::opt::ArgStringList &CC1Args, + Action::OffloadKind DeviceOffloadKind) const { // Pass "-faligned-alloc-unavailable" only when the user hasn't manually // enabled or disabled aligned allocations. if (!DriverArgs.hasArgNoClaim(options::OPT_faligned_allocation, @@ -2922,6 +2967,13 @@ void Darwin::addClangTargetOptions(const llvm::opt::ArgList &DriverArgs, isAlignedAllocationUnavailable()) CC1Args.push_back("-faligned-alloc-unavailable"); + // Pass "-fno-sized-deallocation" only when the user hasn't manually enabled + // or disabled sized deallocations. + if (!DriverArgs.hasArgNoClaim(options::OPT_fsized_deallocation, + options::OPT_fno_sized_deallocation) && + isSizedDeallocationUnavailable()) + CC1Args.push_back("-fno-sized-deallocation"); + addClangCC1ASTargetOptions(DriverArgs, CC1Args); // Enable compatibility mode for NSItemProviderCompletionHandler in diff --git a/clang/lib/Driver/ToolChains/Darwin.h b/clang/lib/Driver/ToolChains/Darwin.h index 10d4b69e5d5f..b45279ecedeb 100644 --- a/clang/lib/Driver/ToolChains/Darwin.h +++ b/clang/lib/Driver/ToolChains/Darwin.h @@ -511,6 +511,10 @@ protected: /// targeting. bool isAlignedAllocationUnavailable() const; + /// Return true if c++14 sized deallocation functions are not implemented in + /// the c++ standard library of the deployment target we are targeting. + bool isSizedDeallocationUnavailable() const; + void addClangTargetOptions(const llvm::opt::ArgList &DriverArgs, llvm::opt::ArgStringList &CC1Args, Action::OffloadKind DeviceOffloadKind) const override; diff --git a/clang/lib/Driver/ToolChains/ZOS.cpp b/clang/lib/Driver/ToolChains/ZOS.cpp index d5fc7b8ef562..074e0556ecd2 100644 --- a/clang/lib/Driver/ToolChains/ZOS.cpp +++ b/clang/lib/Driver/ToolChains/ZOS.cpp @@ -36,6 +36,12 @@ void ZOS::addClangTargetOptions(const ArgList &DriverArgs, if (!DriverArgs.hasArgNoClaim(options::OPT_faligned_allocation, options::OPT_fno_aligned_allocation)) CC1Args.push_back("-faligned-alloc-unavailable"); + + // Pass "-fno-sized-deallocation" only when the user hasn't manually enabled + // or disabled sized deallocations. + if (!DriverArgs.hasArgNoClaim(options::OPT_fsized_deallocation, + options::OPT_fno_sized_deallocation)) + CC1Args.push_back("-fno-sized-deallocation"); } void zos::Assembler::ConstructJob(Compilation &C, const JobAction &JA, diff --git a/clang/test/AST/ast-dump-expr-json.cpp b/clang/test/AST/ast-dump-expr-json.cpp index 4b7365e554cb..dd2fe1fcf60c 100644 --- a/clang/test/AST/ast-dump-expr-json.cpp +++ b/clang/test/AST/ast-dump-expr-json.cpp @@ -2333,7 +2333,7 @@ void TestNonADLCall3() { // CHECK-NEXT: "kind": "FunctionDecl", // CHECK-NEXT: "name": "operator delete", // CHECK-NEXT: "type": { -// CHECK-NEXT: "qualType": "void (void *) noexcept" +// CHECK-NEXT: "qualType": "void (void *, unsigned long) noexcept" // CHECK-NEXT: } // CHECK-NEXT: }, // CHECK-NEXT: "inner": [ diff --git a/clang/test/AST/ast-dump-expr.cpp b/clang/test/AST/ast-dump-expr.cpp index 604868103dab..f9e9ee9d35dd 100644 --- a/clang/test/AST/ast-dump-expr.cpp +++ b/clang/test/AST/ast-dump-expr.cpp @@ -164,7 +164,7 @@ void UnaryExpressions(int *p) { // CHECK-NEXT: DeclRefExpr 0x{{[^ ]*}} 'int *' lvalue ParmVar 0x{{[^ ]*}} 'p' 'int *' ::delete p; - // CHECK: CXXDeleteExpr 0x{{[^ ]*}} 'void' global Function 0x{{[^ ]*}} 'operator delete' 'void (void *) noexcept' + // CHECK: CXXDeleteExpr 0x{{[^ ]*}} 'void' global Function 0x{{[^ ]*}} 'operator delete' 'void (void *, unsigned long) noexcept' // CHECK-NEXT: ImplicitCastExpr // CHECK-NEXT: DeclRefExpr 0x{{[^ ]*}} 'int *' lvalue ParmVar 0x{{[^ ]*}} 'p' 'int *' diff --git a/clang/test/AST/ast-dump-stmt-json.cpp b/clang/test/AST/ast-dump-stmt-json.cpp index 667a12a01202..a473d17da942 100644 --- a/clang/test/AST/ast-dump-stmt-json.cpp +++ b/clang/test/AST/ast-dump-stmt-json.cpp @@ -994,7 +994,7 @@ void TestDependentGenericSelectionExpr(Ty T) { // CHECK-NEXT: "kind": "FunctionDecl", // CHECK-NEXT: "name": "operator delete", // CHECK-NEXT: "type": { -// CHECK-NEXT: "qualType": "void (void *) noexcept" +// CHECK-NEXT: "qualType": "void (void *, unsigned long) noexcept" // CHECK-NEXT: } // CHECK-NEXT: }, // CHECK-NEXT: "inner": [ @@ -1369,7 +1369,7 @@ void TestDependentGenericSelectionExpr(Ty T) { // CHECK-NEXT: "kind": "FunctionDecl", // CHECK-NEXT: "name": "operator delete", // CHECK-NEXT: "type": { -// CHECK-NEXT: "qualType": "void (void *) noexcept" +// CHECK-NEXT: "qualType": "void (void *, unsigned long) noexcept" // CHECK-NEXT: } // CHECK-NEXT: }, // CHECK-NEXT: "inner": [ @@ -1722,7 +1722,6 @@ void TestDependentGenericSelectionExpr(Ty T) { // CHECK-NEXT: "end": {} // CHECK-NEXT: }, // CHECK-NEXT: "isImplicit": true, -// CHECK-NEXT: "isUsed": true, // CHECK-NEXT: "name": "operator delete", // CHECK-NEXT: "mangledName": "_ZdlPv", // CHECK-NEXT: "type": { @@ -1810,6 +1809,126 @@ void TestDependentGenericSelectionExpr(Ty T) { // CHECK-NEXT: } +// CHECK-NOT: {{^}}Dumping +// CHECK: "kind": "FunctionDecl", +// CHECK-NEXT: "loc": {}, +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": {}, +// CHECK-NEXT: "end": {} +// CHECK-NEXT: }, +// CHECK-NEXT: "isImplicit": true, +// CHECK-NEXT: "isUsed": true, +// CHECK-NEXT: "name": "operator delete", +// CHECK-NEXT: "mangledName": "_ZdlPvm", +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "void (void *, unsigned long) noexcept" +// CHECK-NEXT: }, +// CHECK-NEXT: "inner": [ +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "ParmVarDecl", +// CHECK-NEXT: "loc": {}, +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": {}, +// CHECK-NEXT: "end": {} +// CHECK-NEXT: }, +// CHECK-NEXT: "isImplicit": true, +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "void *" +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "ParmVarDecl", +// CHECK-NEXT: "loc": {}, +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": {}, +// CHECK-NEXT: "end": {} +// CHECK-NEXT: }, +// CHECK-NEXT: "isImplicit": true, +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "unsigned long" +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "VisibilityAttr", +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": {}, +// CHECK-NEXT: "end": {} +// CHECK-NEXT: }, +// CHECK-NEXT: "implicit": true, +// CHECK-NEXT: "visibility": "default" +// CHECK-NEXT: } +// CHECK-NEXT: ] +// CHECK-NEXT: } + +// CHECK-NOT: {{^}}Dumping +// CHECK: "kind": "FunctionDecl", +// CHECK-NEXT: "loc": {}, +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": {}, +// CHECK-NEXT: "end": {} +// CHECK-NEXT: }, +// CHECK-NEXT: "isImplicit": true, +// CHECK-NEXT: "name": "operator delete", +// CHECK-NEXT: "mangledName": "_ZdlPvmSt11align_val_t", +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "void (void *, unsigned long, std::align_val_t) noexcept" +// CHECK-NEXT: }, +// CHECK-NEXT: "inner": [ +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "ParmVarDecl", +// CHECK-NEXT: "loc": {}, +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": {}, +// CHECK-NEXT: "end": {} +// CHECK-NEXT: }, +// CHECK-NEXT: "isImplicit": true, +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "void *" +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "ParmVarDecl", +// CHECK-NEXT: "loc": {}, +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": {}, +// CHECK-NEXT: "end": {} +// CHECK-NEXT: }, +// CHECK-NEXT: "isImplicit": true, +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "unsigned long" +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "ParmVarDecl", +// CHECK-NEXT: "loc": {}, +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": {}, +// CHECK-NEXT: "end": {} +// CHECK-NEXT: }, +// CHECK-NEXT: "isImplicit": true, +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "std::align_val_t" +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "VisibilityAttr", +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": {}, +// CHECK-NEXT: "end": {} +// CHECK-NEXT: }, +// CHECK-NEXT: "implicit": true, +// CHECK-NEXT: "visibility": "default" +// CHECK-NEXT: } +// CHECK-NEXT: ] +// CHECK-NEXT: } + // CHECK-NOT: {{^}}Dumping // CHECK: "kind": "FunctionDecl", // CHECK-NEXT: "loc": {}, @@ -1906,6 +2025,125 @@ void TestDependentGenericSelectionExpr(Ty T) { // CHECK-NEXT: } +// CHECK-NOT: {{^}}Dumping +// CHECK: "kind": "FunctionDecl", +// CHECK-NEXT: "loc": {}, +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": {}, +// CHECK-NEXT: "end": {} +// CHECK-NEXT: }, +// CHECK-NEXT: "isImplicit": true, +// CHECK-NEXT: "name": "operator delete[]", +// CHECK-NEXT: "mangledName": "_ZdaPvm", +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "void (void *, unsigned long) noexcept" +// CHECK-NEXT: }, +// CHECK-NEXT: "inner": [ +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "ParmVarDecl", +// CHECK-NEXT: "loc": {}, +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": {}, +// CHECK-NEXT: "end": {} +// CHECK-NEXT: }, +// CHECK-NEXT: "isImplicit": true, +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "void *" +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "ParmVarDecl", +// CHECK-NEXT: "loc": {}, +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": {}, +// CHECK-NEXT: "end": {} +// CHECK-NEXT: }, +// CHECK-NEXT: "isImplicit": true, +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "unsigned long" +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "VisibilityAttr", +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": {}, +// CHECK-NEXT: "end": {} +// CHECK-NEXT: }, +// CHECK-NEXT: "implicit": true, +// CHECK-NEXT: "visibility": "default" +// CHECK-NEXT: } +// CHECK-NEXT: ] +// CHECK-NEXT: } + +// CHECK-NOT: {{^}}Dumping +// CHECK: "kind": "FunctionDecl", +// CHECK-NEXT: "loc": {}, +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": {}, +// CHECK-NEXT: "end": {} +// CHECK-NEXT: }, +// CHECK-NEXT: "isImplicit": true, +// CHECK-NEXT: "name": "operator delete[]", +// CHECK-NEXT: "mangledName": "_ZdaPvmSt11align_val_t", +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "void (void *, unsigned long, std::align_val_t) noexcept" +// CHECK-NEXT: }, +// CHECK-NEXT: "inner": [ +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "ParmVarDecl", +// CHECK-NEXT: "loc": {}, +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": {}, +// CHECK-NEXT: "end": {} +// CHECK-NEXT: }, +// CHECK-NEXT: "isImplicit": true, +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "void *" +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "ParmVarDecl", +// CHECK-NEXT: "loc": {}, +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": {}, +// CHECK-NEXT: "end": {} +// CHECK-NEXT: }, +// CHECK-NEXT: "isImplicit": true, +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "unsigned long" +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "ParmVarDecl", +// CHECK-NEXT: "loc": {}, +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": {}, +// CHECK-NEXT: "end": {} +// CHECK-NEXT: }, +// CHECK-NEXT: "isImplicit": true, +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "std::align_val_t" +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "VisibilityAttr", +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": {}, +// CHECK-NEXT: "end": {} +// CHECK-NEXT: }, +// CHECK-NEXT: "implicit": true, +// CHECK-NEXT: "visibility": "default" +// CHECK-NEXT: } +// CHECK-NEXT: ] +// CHECK-NEXT: } + // CHECK-NOT: {{^}}Dumping // CHECK: "kind": "FunctionTemplateDecl", // CHECK-NEXT: "loc": { diff --git a/clang/test/Analysis/cxxnewexpr-callback.cpp b/clang/test/Analysis/cxxnewexpr-callback.cpp index fe7a9fffad93..7df58cfa9ca2 100644 --- a/clang/test/Analysis/cxxnewexpr-callback.cpp +++ b/clang/test/Analysis/cxxnewexpr-callback.cpp @@ -9,7 +9,7 @@ void free(void *); } // namespace std void *operator new(size_t size) { return std::malloc(size); } -void operator delete(void *ptr) { std::free(ptr); } +void operator delete(void *ptr, size_t size) { std::free(ptr); } struct S { S() {} @@ -49,7 +49,7 @@ void test() { // CHECK-NEXT: PostCall (operator delete) } -void operator delete(void *ptr) { +void operator delete(void *ptr, size_t size) { std::free(ptr); // CHECK-NO-INLINE-NEXT: PreCall (std::free) // CHECK-NO-INLINE-NEXT: PostCall (std::free) diff --git a/clang/test/CXX/basic/basic.stc/basic.stc.dynamic/basic.stc.dynamic.deallocation/p2.cpp b/clang/test/CXX/basic/basic.stc/basic.stc.dynamic/basic.stc.dynamic.deallocation/p2.cpp index 9e3210c6650f..706549f56c52 100644 --- a/clang/test/CXX/basic/basic.stc/basic.stc.dynamic/basic.stc.dynamic.deallocation/p2.cpp +++ b/clang/test/CXX/basic/basic.stc/basic.stc.dynamic/basic.stc.dynamic.deallocation/p2.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -std=c++1z -fsized-deallocation -fexceptions -verify %s +// RUN: %clang_cc1 -std=c++1z -fexceptions -verify %s using size_t = decltype(sizeof(0)); diff --git a/clang/test/CXX/drs/cwg292.cpp b/clang/test/CXX/drs/cwg292.cpp index b05d3b92d627..a7bcbe6f5051 100644 --- a/clang/test/CXX/drs/cwg292.cpp +++ b/clang/test/CXX/drs/cwg292.cpp @@ -1,10 +1,10 @@ -// RUN: %clang_cc1 -std=c++98 %s -triple x86_64-linux-gnu -emit-llvm -disable-llvm-passes -o - -fexceptions -fcxx-exceptions -pedantic-errors | llvm-cxxfilt -n | FileCheck %s --check-prefixes CHECK -// RUN: %clang_cc1 -std=c++11 %s -triple x86_64-linux-gnu -emit-llvm -disable-llvm-passes -o - -fexceptions -fcxx-exceptions -pedantic-errors | llvm-cxxfilt -n | FileCheck %s --check-prefixes CHECK -// RUN: %clang_cc1 -std=c++14 %s -triple x86_64-linux-gnu -emit-llvm -disable-llvm-passes -o - -fexceptions -fcxx-exceptions -pedantic-errors | llvm-cxxfilt -n | FileCheck %s --check-prefixes CHECK -// RUN: %clang_cc1 -std=c++17 %s -triple x86_64-linux-gnu -emit-llvm -disable-llvm-passes -o - -fexceptions -fcxx-exceptions -pedantic-errors | llvm-cxxfilt -n | FileCheck %s --check-prefixes CHECK -// RUN: %clang_cc1 -std=c++20 %s -triple x86_64-linux-gnu -emit-llvm -disable-llvm-passes -o - -fexceptions -fcxx-exceptions -pedantic-errors | llvm-cxxfilt -n | FileCheck %s --check-prefixes CHECK -// RUN: %clang_cc1 -std=c++23 %s -triple x86_64-linux-gnu -emit-llvm -disable-llvm-passes -o - -fexceptions -fcxx-exceptions -pedantic-errors | llvm-cxxfilt -n | FileCheck %s --check-prefixes CHECK -// RUN: %clang_cc1 -std=c++2c %s -triple x86_64-linux-gnu -emit-llvm -disable-llvm-passes -o - -fexceptions -fcxx-exceptions -pedantic-errors | llvm-cxxfilt -n | FileCheck %s --check-prefixes CHECK +// RUN: %clang_cc1 -std=c++98 %s -triple x86_64-linux-gnu -emit-llvm -disable-llvm-passes -o - -fexceptions -fcxx-exceptions -pedantic-errors | llvm-cxxfilt -n | FileCheck %s --check-prefixes CHECK,CXX98-11 +// RUN: %clang_cc1 -std=c++11 %s -triple x86_64-linux-gnu -emit-llvm -disable-llvm-passes -o - -fexceptions -fcxx-exceptions -pedantic-errors | llvm-cxxfilt -n | FileCheck %s --check-prefixes CHECK,CXX98-11 +// RUN: %clang_cc1 -std=c++14 %s -triple x86_64-linux-gnu -emit-llvm -disable-llvm-passes -o - -fexceptions -fcxx-exceptions -pedantic-errors | llvm-cxxfilt -n | FileCheck %s --check-prefixes CHECK,SINCE-CXX14 +// RUN: %clang_cc1 -std=c++17 %s -triple x86_64-linux-gnu -emit-llvm -disable-llvm-passes -o - -fexceptions -fcxx-exceptions -pedantic-errors | llvm-cxxfilt -n | FileCheck %s --check-prefixes CHECK,SINCE-CXX14 +// RUN: %clang_cc1 -std=c++20 %s -triple x86_64-linux-gnu -emit-llvm -disable-llvm-passes -o - -fexceptions -fcxx-exceptions -pedantic-errors | llvm-cxxfilt -n | FileCheck %s --check-prefixes CHECK,SINCE-CXX14 +// RUN: %clang_cc1 -std=c++23 %s -triple x86_64-linux-gnu -emit-llvm -disable-llvm-passes -o - -fexceptions -fcxx-exceptions -pedantic-errors | llvm-cxxfilt -n | FileCheck %s --check-prefixes CHECK,SINCE-CXX14 +// RUN: %clang_cc1 -std=c++2c %s -triple x86_64-linux-gnu -emit-llvm -disable-llvm-passes -o - -fexceptions -fcxx-exceptions -pedantic-errors | llvm-cxxfilt -n | FileCheck %s --check-prefixes CHECK,SINCE-CXX14 namespace cwg292 { // cwg292: 2.9 @@ -23,7 +23,8 @@ void f() { // CHECK: invoke {{.*}} i32 @cwg292::g()() // CHECK-NEXT: to {{.*}} unwind label %lpad // CHECK-LABEL: lpad: -// CHECK: call void @operator delete(void*)(ptr {{.*}} %[[CALL]]) +// CXX98-11: call void @operator delete(void*)(ptr {{.*}} %[[CALL]]) +// SINCE-CXX14: call void @operator delete(void*, unsigned long)(ptr {{.*}} %[[CALL]], i64 noundef 1) // CHECK-LABEL: eh.resume: // CHECK-LABEL: } diff --git a/clang/test/CXX/expr/expr.unary/expr.new/p14.cpp b/clang/test/CXX/expr/expr.unary/expr.new/p14.cpp index 6537cdcfeafa..d0b24c8fe47b 100644 --- a/clang/test/CXX/expr/expr.unary/expr.new/p14.cpp +++ b/clang/test/CXX/expr/expr.unary/expr.new/p14.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -std=c++1z -fsized-deallocation -fexceptions %s -verify +// RUN: %clang_cc1 -std=c++1z -fexceptions %s -verify using size_t = decltype(sizeof(0)); namespace std { enum class align_val_t : size_t {}; } diff --git a/clang/test/CodeGenCXX/cxx1y-sized-deallocation.cpp b/clang/test/CodeGenCXX/cxx1y-sized-deallocation.cpp index 4e1565725152..55913aff9c19 100644 --- a/clang/test/CodeGenCXX/cxx1y-sized-deallocation.cpp +++ b/clang/test/CodeGenCXX/cxx1y-sized-deallocation.cpp @@ -1,12 +1,12 @@ // Check that delete exprs call the sized deallocation function if -// -fsized-deallocation is passed in both C++11 and C++14. +// -fsized-deallocation is passed in C++11 or std >= C++14. // RUN: %clang_cc1 -std=c++11 -fsized-deallocation %s -emit-llvm -triple x86_64-linux-gnu -o - | FileCheck %s -// RUN: %clang_cc1 -std=c++14 -fsized-deallocation %s -emit-llvm -triple x86_64-linux-gnu -o - | FileCheck %s +// RUN: %clang_cc1 -std=c++14 %s -emit-llvm -triple x86_64-linux-gnu -o - | FileCheck %s -// Check that we don't used sized deallocation without -fsized-deallocation and -// C++14. +// Check that we don't used sized deallocation with -fno-sized-deallocation or without C++14. // RUN: %clang_cc1 -std=c++11 %s -emit-llvm -triple x86_64-linux-gnu -o - | FileCheck %s --check-prefix=CHECK-UNSIZED -// RUN: %clang_cc1 -std=c++14 %s -emit-llvm -triple x86_64-linux-gnu -o - | FileCheck %s --check-prefix=CHECK-UNSIZED +// RUN: %clang_cc1 -std=c++14 %s -emit-llvm -triple x86_64-linux-gnu -fno-sized-deallocation -o - \ +// RUN: | FileCheck %s --check-prefix=CHECK-UNSIZED // CHECK-UNSIZED-NOT: _ZdlPvm // CHECK-UNSIZED-NOT: _ZdaPvm diff --git a/clang/test/CodeGenCXX/cxx1z-aligned-allocation.cpp b/clang/test/CodeGenCXX/cxx1z-aligned-allocation.cpp index ab2e4b3cdbbf..8823bc64a436 100644 --- a/clang/test/CodeGenCXX/cxx1z-aligned-allocation.cpp +++ b/clang/test/CodeGenCXX/cxx1z-aligned-allocation.cpp @@ -1,10 +1,10 @@ // Check that delete exprs call aligned (de)allocation functions if // -faligned-allocation is passed in both C++11 and C++14. // RUN: %clang_cc1 -std=c++11 -fexceptions -fsized-deallocation -faligned-allocation %s -emit-llvm -triple x86_64-linux-gnu -o - | FileCheck %s -// RUN: %clang_cc1 -std=c++14 -fexceptions -fsized-deallocation -faligned-allocation %s -emit-llvm -triple x86_64-linux-gnu -o - | FileCheck %s -// RUN: %clang_cc1 -std=c++1z -fexceptions -fsized-deallocation %s -emit-llvm -triple x86_64-linux-gnu -o - | FileCheck %s +// RUN: %clang_cc1 -std=c++14 -fexceptions -faligned-allocation %s -emit-llvm -triple x86_64-linux-gnu -o - | FileCheck %s +// RUN: %clang_cc1 -std=c++1z -fexceptions %s -emit-llvm -triple x86_64-linux-gnu -o - | FileCheck %s -// RUN: %clang_cc1 -std=c++1z -fexceptions -fsized-deallocation %s -emit-llvm -triple x86_64-windows-msvc -o - | FileCheck %s --check-prefix=CHECK-MS +// RUN: %clang_cc1 -std=c++1z -fexceptions %s -emit-llvm -triple x86_64-windows-msvc -o - | FileCheck %s --check-prefix=CHECK-MS // Check that we don't used aligned (de)allocation without -faligned-allocation or C++1z. // RUN: %clang_cc1 -std=c++14 -DUNALIGNED -fexceptions %s -emit-llvm -triple x86_64-linux-gnu -o - | FileCheck %s --check-prefix=CHECK-UNALIGNED diff --git a/clang/test/CodeGenCXX/cxx2a-destroying-delete.cpp b/clang/test/CodeGenCXX/cxx2a-destroying-delete.cpp index 20264b67353a..f6f4a2ff735c 100644 --- a/clang/test/CodeGenCXX/cxx2a-destroying-delete.cpp +++ b/clang/test/CodeGenCXX/cxx2a-destroying-delete.cpp @@ -108,10 +108,10 @@ struct J { // CHECK-MSABI-LABEL: define {{.*}}@"?j@@ J *j() { // CHECK-ITANIUM: invoke {{.*}}@_ZN1JC1Ev( - // CHECK-ITANIUM: call {{.*}}@_ZdlPv( + // CHECK-ITANIUM: call {{.*}}@_ZdlPvm( // CHECK-NOT: } // CHECK-MSABI: invoke {{.*}}@"??0J@@Q{{AE|EAA}}@XZ"( - // CHECK-MSABI: call {{.*}}@"??3@YAXP{{E?}}AX@Z"( + // CHECK-MSABI: call {{.*}}@"??3@YAXP{{E?}}AX{{I|_K}}@Z"( return new J; // CHECK: } } diff --git a/clang/test/CodeGenCXX/delete-two-arg.cpp b/clang/test/CodeGenCXX/delete-two-arg.cpp index 552634f430a8..a0dcd03bc5a9 100644 --- a/clang/test/CodeGenCXX/delete-two-arg.cpp +++ b/clang/test/CodeGenCXX/delete-two-arg.cpp @@ -43,7 +43,9 @@ namespace test2 { // CHECK-NEXT: br i1 [[T1]], // CHECK: [[T3:%.*]] = getelementptr inbounds i8, ptr [[T0]], i32 -4 // CHECK-NEXT: [[T5:%.*]] = load i32, ptr [[T3]] - // CHECK-NEXT: call void @_ZdaPv(ptr noundef [[T3]]) + // CHECK-NEXT: [[T6:%.*]] = mul i32 4, [[T5]] + // CHECK-NEXT: [[T7:%.*]] = add i32 [[T6]], 4 + // CHECK-NEXT: call void @_ZdaPvj(ptr noundef [[T3]], i32 noundef [[T7]]) // CHECK-NEXT: br label ::delete[] p; } diff --git a/clang/test/CodeGenCXX/delete.cpp b/clang/test/CodeGenCXX/delete.cpp index 1a418f48b659..d5b0dc671291 100644 --- a/clang/test/CodeGenCXX/delete.cpp +++ b/clang/test/CodeGenCXX/delete.cpp @@ -16,7 +16,7 @@ void t3(S *s) { // CHECK: icmp {{.*}} null // CHECK: br i1 - // CHECK: call void @_ZdlPv + // CHECK: call void @_ZdlPvm // Check the delete is inside the 'if !null' check unless we're optimizing // for size. FIXME: We could omit the branch entirely in this case. @@ -35,7 +35,7 @@ struct T { void t4(T *t) { // CHECK: call void @_ZN1TD1Ev // CHECK-SIZE-NEXT: br - // CHECK: call void @_ZdlPv + // CHECK: call void @_ZdlPvm delete t; } @@ -93,14 +93,16 @@ namespace test1 { // CHECK-NEXT: call void @_ZN5test11AD1Ev(ptr {{[^,]*}} [[CUR]]) // CHECK-NEXT: [[ISDONE:%.*]] = icmp eq ptr [[CUR]], [[BEGIN]] // CHECK-NEXT: br i1 [[ISDONE]] - // CHECK: call void @_ZdaPv(ptr noundef [[ALLOC]]) + // CHECK: [[MUL:%.*]] = mul i64 4, [[COUNT]] + // CHECK-NEXT: [[SIZE:%.*]] = add i64 [[MUL]], 8 + // CHECK-NEXT: call void @_ZdaPvm(ptr noundef [[ALLOC]], i64 noundef [[SIZE]]) } } namespace test2 { // CHECK-LABEL: define{{.*}} void @_ZN5test21fEPb void f(bool *b) { - // CHECK: call void @_ZdlPv(ptr + // CHECK: call void @_ZdlPvm(ptr{{.*}}i64 delete b; // CHECK: call void @_ZdaPv(ptr delete [] b; @@ -137,7 +139,7 @@ namespace test4 { // CHECK-NEXT: [[DTOR:%.*]] = load ptr, ptr [[T0]] // CHECK-NEXT: call void [[DTOR]](ptr {{[^,]*}} [[OBJ:%.*]]) // Call the global operator delete. - // CHECK-NEXT: call void @_ZdlPv(ptr noundef [[ALLOCATED]]) [[NUW:#[0-9]+]] + // CHECK-NEXT: call void @_ZdlPvm(ptr noundef [[ALLOCATED]], i64 noundef 8) [[NUW:#[0-9]+]] ::delete xp; } } diff --git a/clang/test/CodeGenCXX/dllimport.cpp b/clang/test/CodeGenCXX/dllimport.cpp index 6fec2f2982d4..484866b45389 100644 --- a/clang/test/CodeGenCXX/dllimport.cpp +++ b/clang/test/CodeGenCXX/dllimport.cpp @@ -205,7 +205,7 @@ USEVAR(VarTmpl) // Functions //===----------------------------------------------------------------------===// -// GNU-DAG: declare dso_local void @_ZdlPv(ptr) +// GNU-DAG: declare dso_local void @_ZdlPv{{j|y}}(ptr, i{{32|64}}) // Import function declaration. // MSC-DAG: declare dllimport void @"?decl@@YAXXZ"() @@ -358,7 +358,7 @@ __declspec(dllimport) void operator delete(void*); __declspec(dllimport) inline int *ReferencingImportedNew() { return new int[2]; } // MO1-DAG: define available_externally dllimport ptr @"?ReferencingImportedNew@@YAPAHXZ" __declspec(dllimport) inline int *ReferencingImportedDelete() { delete (int*)nullptr; } -// MO1-DAG: define available_externally dllimport ptr @"?ReferencingImportedDelete@@YAPAHXZ" +// MO1-DAG: declare dllimport ptr @"?ReferencingImportedDelete@@YAPAHXZ" USE(ReferencingImportedNew) USE(ReferencingImportedDelete) struct ClassWithDtor { ~ClassWithDtor() {} }; diff --git a/clang/test/CodeGenCXX/new.cpp b/clang/test/CodeGenCXX/new.cpp index e278d9acfe9e..af225529c494 100644 --- a/clang/test/CodeGenCXX/new.cpp +++ b/clang/test/CodeGenCXX/new.cpp @@ -15,7 +15,7 @@ void t1() { } // CHECK: declare noundef nonnull ptr @_Znwm(i64 noundef) [[ATTR_NOBUILTIN:#[^ ]*]] -// CHECK: declare void @_ZdlPv(ptr noundef) [[ATTR_NOBUILTIN_NOUNWIND:#[^ ]*]] +// CHECK: declare void @_ZdlPvm(ptr noundef, i64 noundef) [[ATTR_NOBUILTIN_NOUNWIND:#[^ ]*]] // CHECK: declare noundef nonnull ptr @_Znam(i64 noundef) [[ATTR_NOBUILTIN]] // CHECK: declare void @_ZdaPv(ptr noundef) [[ATTR_NOBUILTIN_NOUNWIND]] @@ -192,7 +192,7 @@ void f() { // CHECK: store i64 200 delete[] new (nothrow) Alloc[10][20]; // CHECK: call noalias noundef nonnull ptr @_Znwm - // CHECK: call void @_ZdlPv(ptr + // CHECK: call void @_ZdlPvm(ptr noundef {{%.*}}, i64 noundef 1) delete new bool; // CHECK: ret void } @@ -317,7 +317,7 @@ namespace N3664 { void f() { // CHECK: call noalias noundef nonnull ptr @_Znwm(i64 noundef 4) [[ATTR_BUILTIN_NEW:#[^ ]*]] int *p = new int; // expected-note {{allocated with 'new' here}} - // CHECK: call void @_ZdlPv({{.*}}) [[ATTR_BUILTIN_DELETE:#[^ ]*]] + // CHECK: call void @_ZdlPvm({{.*}}) [[ATTR_BUILTIN_DELETE:#[^ ]*]] delete p; // CHECK: call noalias noundef nonnull ptr @_Znam(i64 noundef 12) [[ATTR_BUILTIN_NEW]] diff --git a/clang/test/CodeGenCoroutines/coro-aligned-alloc-2.cpp b/clang/test/CodeGenCoroutines/coro-aligned-alloc-2.cpp index 21c2e45b890f..bfa124bb4dc4 100644 --- a/clang/test/CodeGenCoroutines/coro-aligned-alloc-2.cpp +++ b/clang/test/CodeGenCoroutines/coro-aligned-alloc-2.cpp @@ -1,9 +1,7 @@ // Tests that the combination of -fcoro-aligned-allocation and -fsized-deallocation works well. // Test the compiler will chose sized deallocation correctly. -// This is only enabled with `-fsized-deallocation` which is off by default. // RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -std=c++20 \ // RUN: -fcoro-aligned-allocation -emit-llvm %s -o - -disable-llvm-passes \ -// RUN: -fsized-deallocation \ // RUN: | FileCheck %s #include "Inputs/coroutine.h" diff --git a/clang/test/CodeGenCoroutines/coro-aligned-alloc.cpp b/clang/test/CodeGenCoroutines/coro-aligned-alloc.cpp index 8019926b730c..156fa64f454c 100644 --- a/clang/test/CodeGenCoroutines/coro-aligned-alloc.cpp +++ b/clang/test/CodeGenCoroutines/coro-aligned-alloc.cpp @@ -26,8 +26,9 @@ struct task { // CHECK: %[[aligned_new:.+]] = call{{.*}}@_ZnwmSt11align_val_t({{.*}}%[[coro_size]],{{.*}}%[[coro_align]]) // CHECK: coro.free: +// CHECK: %[[coro_size_for_free:.+]] = call{{.*}}@llvm.coro.size // CHECK: %[[coro_align_for_free:.+]] = call{{.*}}@llvm.coro.align -// CHECK: call void @_ZdlPvSt11align_val_t({{.*}}[[coro_align_for_free]] +// CHECK: call void @_ZdlPvmSt11align_val_t({{.*}}%[[coro_size_for_free]],{{.*}}%[[coro_align_for_free]]) task f() { co_return 43; @@ -58,8 +59,9 @@ void *operator new(std::size_t, std::align_val_t, std::nothrow_t) noexcept; // CHECK: %[[aligned_new:.+]] = call{{.*}}@_ZnwmSt11align_val_tSt9nothrow_t({{.*}}%[[coro_size]],{{.*}}%[[coro_align]]) // CHECK: coro.free: +// CHECK: %[[coro_size_for_free:.+]] = call{{.*}}@llvm.coro.size // CHECK: %[[coro_align_for_free:.+]] = call{{.*}}@llvm.coro.align -// CHECK: call void @_ZdlPvSt11align_val_t({{.*}}[[coro_align_for_free]] +// CHECK: call void @_ZdlPvmSt11align_val_t({{.*}}%[[coro_size_for_free]],{{.*}}%[[coro_align_for_free]]) task2 f2() { co_return 43; diff --git a/clang/test/CodeGenCoroutines/coro-alloc.cpp b/clang/test/CodeGenCoroutines/coro-alloc.cpp index d026a0d7df22..7b3be7e0b7f9 100644 --- a/clang/test/CodeGenCoroutines/coro-alloc.cpp +++ b/clang/test/CodeGenCoroutines/coro-alloc.cpp @@ -70,7 +70,8 @@ extern "C" void f0(global_new_delete_tag) { // CHECK: br i1 %[[NeedDealloc]], label %[[FreeBB:.+]], label %[[Afterwards:.+]] // CHECK: [[FreeBB]]: - // CHECK: call void @_ZdlPv(ptr noundef %[[MEM]]) + // CHECK: %[[SIZE:.+]] = call i64 @llvm.coro.size.i64() + // CHECK: call void @_ZdlPvm(ptr noundef %[[MEM]], i64 noundef %[[SIZE]]) // CHECK: br label %[[Afterwards]] // CHECK: [[Afterwards]]: @@ -99,7 +100,8 @@ extern "C" void f1(promise_new_tag ) { // CHECK: %[[FRAME:.+]] = call ptr @llvm.coro.begin( // CHECK: %[[MEM:.+]] = call ptr @llvm.coro.free(token %[[ID]], ptr %[[FRAME]]) - // CHECK: call void @_ZdlPv(ptr noundef %[[MEM]]) + // CHECK: %[[SIZE:.+]] = call i64 @llvm.coro.size.i64() + // CHECK: call void @_ZdlPvm(ptr noundef %[[MEM]], i64 noundef %[[SIZE]]) co_return; } diff --git a/clang/test/CodeGenCoroutines/coro-cleanup.cpp b/clang/test/CodeGenCoroutines/coro-cleanup.cpp index 98f150758e2d..4e77ac25af1b 100644 --- a/clang/test/CodeGenCoroutines/coro-cleanup.cpp +++ b/clang/test/CodeGenCoroutines/coro-cleanup.cpp @@ -84,11 +84,13 @@ void f() { // CHECK: [[Cleanup]]: // CHECK: call void @_ZNSt16coroutine_traitsIJvEE12promise_typeD1Ev( // CHECK: %[[Mem0:.+]] = call ptr @llvm.coro.free( - // CHECK: call void @_ZdlPv(ptr noundef %[[Mem0]] + // CHECK: %[[SIZE:.+]] = call i64 @llvm.coro.size.i64() + // CHECK: call void @_ZdlPvm(ptr noundef %[[Mem0]], i64 noundef %[[SIZE]]) // CHECK: [[Dealloc]]: // THROWEND: %[[Mem:.+]] = call ptr @llvm.coro.free( - // THROWEND: call void @_ZdlPv(ptr noundef %[[Mem]]) + // THROWEND: %[[SIZE:.+]] = call i64 @llvm.coro.size.i64() + // THROWEND: call void @_ZdlPvm(ptr noundef %[[Mem]], i64 noundef %[[SIZE]]) co_return; } diff --git a/clang/test/CodeGenCoroutines/coro-dealloc.cpp b/clang/test/CodeGenCoroutines/coro-dealloc.cpp index 3cdba6cafdc0..5a699ac9b585 100644 --- a/clang/test/CodeGenCoroutines/coro-dealloc.cpp +++ b/clang/test/CodeGenCoroutines/coro-dealloc.cpp @@ -1,6 +1,5 @@ // RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -std=c++20 \ // RUN: -emit-llvm %s -o - -disable-llvm-passes \ -// RUN: -fsized-deallocation \ // RUN: | FileCheck %s #include "Inputs/coroutine.h" @@ -21,7 +20,6 @@ struct task { }; // Test the compiler will chose sized deallocation correctly. -// This is only enabled with `-fsized-deallocation` which is off by default. void operator delete(void *ptr, std::size_t size) noexcept; // CHECK: define{{.*}}@_Z1fv diff --git a/clang/test/CodeGenCoroutines/coro-gro.cpp b/clang/test/CodeGenCoroutines/coro-gro.cpp index d4c3ff589e34..b62134317cef 100644 --- a/clang/test/CodeGenCoroutines/coro-gro.cpp +++ b/clang/test/CodeGenCoroutines/coro-gro.cpp @@ -51,7 +51,8 @@ int f() { // CHECK: call void @_ZNSt16coroutine_traitsIiJEE12promise_typeD1Ev( // CHECK: %[[Mem:.+]] = call ptr @llvm.coro.free( - // CHECK: call void @_ZdlPv(ptr noundef %[[Mem]]) + // CHECK: %[[SIZE:.+]] = call i64 @llvm.coro.size.i64() + // CHECK: call void @_ZdlPvm(ptr noundef %[[Mem]], i64 noundef %[[SIZE]]) // Initialize retval from Gro and destroy Gro // Note this also tests delaying initialization when Gro and function return diff --git a/clang/test/CodeGenCoroutines/pr56919.cpp b/clang/test/CodeGenCoroutines/pr56919.cpp index c7de08ef72d7..baa8c27ce664 100644 --- a/clang/test/CodeGenCoroutines/pr56919.cpp +++ b/clang/test/CodeGenCoroutines/pr56919.cpp @@ -111,12 +111,15 @@ Task Bar() { co_await Baz(); } // CHECK: _Z3Quxv.destroy:{{.*}} // CHECK-NEXT: # -// CHECK-NEXT: jmp _ZdlPv +// CHECK-NEXT: movl $40, %esi +// CHECK-NEXT: jmp _ZdlPvm@PLT // CHECK: _Z3Bazv.destroy:{{.*}} // CHECK-NEXT: # -// CHECK-NEXT: jmp _ZdlPv +// CHECK-NEXT: movl $80, %esi +// CHECK-NEXT: jmp _ZdlPvm // CHECK: _Z3Barv.destroy:{{.*}} // CHECK-NEXT: # -// CHECK-NEXT: jmp _ZdlPv +// CHECK-NEXT: movl $120, %esi +// CHECK-NEXT: jmp _ZdlPvm diff --git a/clang/test/Lexer/cxx-features.cpp b/clang/test/Lexer/cxx-features.cpp index 41550cf02aa3..4c2aa3ae2c54 100644 --- a/clang/test/Lexer/cxx-features.cpp +++ b/clang/test/Lexer/cxx-features.cpp @@ -1,17 +1,17 @@ // RUN: %clang_cc1 -std=c++98 -fcxx-exceptions -verify %s // RUN: %clang_cc1 -std=c++11 -fcxx-exceptions -verify %s -// RUN: %clang_cc1 -std=c++14 -fcxx-exceptions -fsized-deallocation -verify %s -// RUN: %clang_cc1 -std=c++17 -fcxx-exceptions -fsized-deallocation -verify %s -// RUN: %clang_cc1 -std=c++20 -fcxx-exceptions -fsized-deallocation -verify %s -// RUN: %clang_cc1 -std=c++23 -fcxx-exceptions -fsized-deallocation -verify %s -// RUN: %clang_cc1 -std=c++2c -fcxx-exceptions -fsized-deallocation -verify %s +// RUN: %clang_cc1 -std=c++14 -fcxx-exceptions -verify %s +// RUN: %clang_cc1 -std=c++17 -fcxx-exceptions -verify %s +// RUN: %clang_cc1 -std=c++20 -fcxx-exceptions -verify %s +// RUN: %clang_cc1 -std=c++23 -fcxx-exceptions -verify %s +// RUN: %clang_cc1 -std=c++2c -fcxx-exceptions -verify %s // -// RUN: %clang_cc1 -std=c++17 -fcxx-exceptions -fsized-deallocation -fno-relaxed-template-template-args -DNO_RELAXED_TEMPLATE_TEMPLATE_ARGS=1 -verify %s -// RUN: %clang_cc1 -std=c++17 -fcxx-exceptions -fsized-deallocation -DCONCEPTS_TS=1 -verify %s -// RUN: %clang_cc1 -std=c++14 -fno-rtti -fno-threadsafe-statics -verify %s -DNO_EXCEPTIONS -DNO_RTTI -DNO_THREADSAFE_STATICS -fsized-deallocation -// RUN: %clang_cc1 -std=c++14 -fchar8_t -DNO_EXCEPTIONS -DCHAR8_T -verify -fsized-deallocation %s -// RUN: %clang_cc1 -std=c++2a -fno-char8_t -DNO_EXCEPTIONS -DNO_CHAR8_T -verify -fsized-deallocation %s +// RUN: %clang_cc1 -std=c++17 -fcxx-exceptions -fno-relaxed-template-template-args -DNO_RELAXED_TEMPLATE_TEMPLATE_ARGS=1 -verify %s +// RUN: %clang_cc1 -std=c++17 -fcxx-exceptions -DCONCEPTS_TS=1 -verify %s +// RUN: %clang_cc1 -std=c++14 -fno-rtti -fno-threadsafe-statics -verify %s -DNO_EXCEPTIONS -DNO_RTTI -DNO_THREADSAFE_STATICS +// RUN: %clang_cc1 -std=c++14 -fchar8_t -DNO_EXCEPTIONS -DCHAR8_T -verify %s +// RUN: %clang_cc1 -std=c++2a -fno-char8_t -DNO_EXCEPTIONS -DNO_CHAR8_T -verify %s // expected-no-diagnostics diff --git a/clang/test/PCH/cxx1z-aligned-alloc.cpp b/clang/test/PCH/cxx1z-aligned-alloc.cpp index c1becbde3bf2..cccd62859784 100644 --- a/clang/test/PCH/cxx1z-aligned-alloc.cpp +++ b/clang/test/PCH/cxx1z-aligned-alloc.cpp @@ -1,12 +1,12 @@ // No PCH: -// RUN: %clang_cc1 -pedantic -fsized-deallocation -std=c++1z -include %s -verify %s +// RUN: %clang_cc1 -pedantic -std=c++1z -include %s -verify %s // // With PCH: -// RUN: %clang_cc1 -pedantic -fsized-deallocation -std=c++1z -emit-pch %s -o %t -// RUN: %clang_cc1 -pedantic -fsized-deallocation -std=c++1z -include-pch %t -verify %s +// RUN: %clang_cc1 -pedantic -std=c++1z -emit-pch %s -o %t +// RUN: %clang_cc1 -pedantic -std=c++1z -include-pch %t -verify %s -// RUN: %clang_cc1 -pedantic -fsized-deallocation -std=c++1z -emit-pch -fpch-instantiate-templates %s -o %t -// RUN: %clang_cc1 -pedantic -fsized-deallocation -std=c++1z -include-pch %t -verify %s +// RUN: %clang_cc1 -pedantic -std=c++1z -emit-pch -fpch-instantiate-templates %s -o %t +// RUN: %clang_cc1 -pedantic -std=c++1z -include-pch %t -verify %s // expected-no-diagnostics diff --git a/clang/test/SemaCXX/MicrosoftExtensions.cpp b/clang/test/SemaCXX/MicrosoftExtensions.cpp index 7286217b1644..98c19975095b 100644 --- a/clang/test/SemaCXX/MicrosoftExtensions.cpp +++ b/clang/test/SemaCXX/MicrosoftExtensions.cpp @@ -571,11 +571,17 @@ class PR34109_class { virtual ~PR34109_class() {} }; +#if !defined(__cpp_sized_deallocation) void operator delete(void *) throw(); // expected-note@-1 {{previous declaration is here}} __declspec(dllexport) void operator delete(void *) throw(); // expected-error@-1 {{redeclaration of 'operator delete' cannot add 'dllexport' attribute}} - +#else +void operator delete(void *, unsigned int) throw(); +// expected-note@-1 {{previous declaration is here}} +__declspec(dllexport) void operator delete(void *, unsigned int) throw(); +// expected-error@-1 {{redeclaration of 'operator delete' cannot add 'dllexport' attribute}} +#endif void PR34109(int* a) { delete a; } diff --git a/clang/test/SemaCXX/builtin-operator-new-delete.cpp b/clang/test/SemaCXX/builtin-operator-new-delete.cpp index 6fcff92dc095..db15616803e3 100644 --- a/clang/test/SemaCXX/builtin-operator-new-delete.cpp +++ b/clang/test/SemaCXX/builtin-operator-new-delete.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -std=c++1z -fsyntax-only -verify %s +// RUN: %clang_cc1 -std=c++1z -fno-sized-deallocation -fsyntax-only -verify %s // RUN: %clang_cc1 -std=c++03 -fsyntax-only -verify %s // RUN: %clang_cc1 -std=c++03 -faligned-allocation -fsyntax-only -verify %s // RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s diff --git a/clang/test/SemaCXX/cxx1y-sized-deallocation.cpp b/clang/test/SemaCXX/cxx1y-sized-deallocation.cpp index 3ec65a6a64d1..462f1725bb1c 100644 --- a/clang/test/SemaCXX/cxx1y-sized-deallocation.cpp +++ b/clang/test/SemaCXX/cxx1y-sized-deallocation.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -std=c++1y -verify %s -fsized-deallocation -fexceptions -fcxx-exceptions +// RUN: %clang_cc1 -std=c++1y -verify %s -fexceptions -fcxx-exceptions using size_t = decltype(sizeof(0)); void operator delete(void *, size_t) noexcept; // expected-note {{'operator delete' declared here}} diff --git a/clang/test/SemaCXX/unavailable_aligned_allocation.cpp b/clang/test/SemaCXX/unavailable_aligned_allocation.cpp index be593eafe11d..45fdec606ad1 100644 --- a/clang/test/SemaCXX/unavailable_aligned_allocation.cpp +++ b/clang/test/SemaCXX/unavailable_aligned_allocation.cpp @@ -75,7 +75,7 @@ void testOveraligned() { // expected-error-re@-22 {{aligned deallocation function of type 'void (void *, enum std::align_val_t) noexcept' is {{only|not}} available on}} // expected-note@-23 {{if you supply your own aligned allocation functions}} -// expected-error-re@-24 {{aligned deallocation function of type 'void (void *, enum std::align_val_t) noexcept' is {{only|not}} available on}} +// expected-error-re@-24 {{aligned deallocation function of type 'void (void *, std::size_t, std::align_val_t) noexcept' is {{only|not}} available on}} // expected-note@-25 {{if you supply your own aligned allocation functions}} // expected-error-re@-26 {{aligned allocation function of type 'void *(std::size_t, std::align_val_t, const std::nothrow_t &) noexcept' is {{only|not}} available on}} @@ -143,19 +143,19 @@ OveralignedS2::~OveralignedS2() {} // expected-no-diagnostics #else #if defined(IOS) -// expected-error@-6 {{aligned deallocation function of type 'void (void *, enum std::align_val_t) noexcept' is only available on iOS 11 or newer}}} +// expected-error@-6 {{aligned deallocation function of type 'void (void *, std::size_t, std::align_val_t) noexcept' is only available on iOS 11 or newer}}} // expected-note@-7 {{if you supply your own aligned allocation functions}} #elif defined(TVOS) -// expected-error@-9 {{aligned deallocation function of type 'void (void *, enum std::align_val_t) noexcept' is only available on tvOS 11 or newer}}} +// expected-error@-9 {{aligned deallocation function of type 'void (void *, std::size_t, std::align_val_t) noexcept' is only available on tvOS 11 or newer}}} // expected-note@-10 {{if you supply your own aligned allocation functions}} #elif defined(WATCHOS) -// expected-error@-12 {{aligned deallocation function of type 'void (void *, enum std::align_val_t) noexcept' is only available on watchOS 4 or newer}}} +// expected-error@-12 {{aligned deallocation function of type 'void (void *, std::size_t, std::align_val_t) noexcept' is only available on watchOS 4 or newer}}} // expected-note@-13 {{if you supply your own aligned allocation functions}} #elif defined(MACOS) -// expected-error@-15 {{aligned deallocation function of type 'void (void *, enum std::align_val_t) noexcept' is only available on macOS 10.13 or newer}}} +// expected-error@-15 {{aligned deallocation function of type 'void (void *, std::size_t, std::align_val_t) noexcept' is only available on macOS 10.13 or newer}}} // expected-note@-16 {{if you supply your own aligned allocation functions}} #elif defined(ZOS) -// expected-error@-18 {{aligned deallocation function of type 'void (void *, enum std::align_val_t) noexcept' is not available on z/OS}}} +// expected-error@-18 {{aligned deallocation function of type 'void (void *, std::size_t, std::align_val_t) noexcept' is not available on z/OS}}} // expected-note@-19 {{if you supply your own aligned allocation functions}} #endif #endif @@ -209,6 +209,9 @@ void *operator new(std::size_t __sz, std::align_val_t) { void operator delete(void *p, std::align_val_t) { } +void operator delete(void *p, std::size_t __sz, std::align_val_t) { +} + void testOveraligned2() { auto p = new ((std::align_val_t)8) OveralignedS; delete p; diff --git a/clang/tools/clang-repl/CMakeLists.txt b/clang/tools/clang-repl/CMakeLists.txt index d3dec1984b78..4017b1445da0 100644 --- a/clang/tools/clang-repl/CMakeLists.txt +++ b/clang/tools/clang-repl/CMakeLists.txt @@ -11,6 +11,49 @@ add_clang_tool(clang-repl ClangRepl.cpp ) +if(MSVC) + set_target_properties(clang-repl PROPERTIES WINDOWS_EXPORT_ALL_SYMBOLS 1) + + # RTTI/C++ symbols + set(clang_repl_exports ${clang_repl_exports} ??_7type_info@@6B@ + ?__type_info_root_node@@3U__type_info_node@@A + ?nothrow@std@@3Unothrow_t@1@B + ) + + # Compiler added symbols for static variables. NOT for VStudio < 2015 + set(clang_repl_exports ${clang_repl_exports} _Init_thread_abort _Init_thread_epoch + _Init_thread_footer _Init_thread_header _tls_index + ) + + if(CMAKE_SIZEOF_VOID_P EQUAL 8) + # new/delete variants needed when linking to static msvc runtime (esp. Debug) + set(clang_repl_exports ${clang_repl_exports} + ??2@YAPEAX_K@Z + ??3@YAXPEAX@Z + ??_U@YAPEAX_K@Z + ??_V@YAXPEAX@Z + ??3@YAXPEAX_K@Z + ) + else() + set(clang_repl_exports ${clang_repl_exports} + ??2@YAPAXI@Z + ??3@YAXPAX@Z + ??3@YAXPAXI@Z + ??_U@YAPAXI@Z + ??_V@YAXPAX@Z + ??_V@YAXPAXI@Z + ) + endif() + + # List to '/EXPORT:sym0 /EXPORT:sym1 /EXPORT:sym2 ...' + foreach(sym ${clang_repl_exports}) + set(clang_repl_link_str "${clang_repl_link_str} /EXPORT:${sym}") + endforeach(sym ${clang_repl_exports}) + + set_property(TARGET clang-repl APPEND_STRING PROPERTY LINK_FLAGS ${clang_repl_link_str}) + +endif(MSVC) + clang_target_link_libraries(clang-repl PRIVATE clangAST clangBasic diff --git a/clang/unittests/Interpreter/CMakeLists.txt b/clang/unittests/Interpreter/CMakeLists.txt index e5a77e77de75..c0fd2d8f3777 100644 --- a/clang/unittests/Interpreter/CMakeLists.txt +++ b/clang/unittests/Interpreter/CMakeLists.txt @@ -29,3 +29,46 @@ if(NOT WIN32) endif() export_executable_symbols(ClangReplInterpreterTests) + +if(MSVC) + set_target_properties(ClangReplInterpreterTests PROPERTIES WINDOWS_EXPORT_ALL_SYMBOLS 1) + + # RTTI/C++ symbols + set(ClangReplInterpreterTests_exports ${ClangReplInterpreterTests_exports} ??_7type_info@@6B@ + ?__type_info_root_node@@3U__type_info_node@@A + ?nothrow@std@@3Unothrow_t@1@B + ) + + # Compiler added symbols for static variables. NOT for VStudio < 2015 + set(ClangReplInterpreterTests_exports ${ClangReplInterpreterTests_exports} _Init_thread_abort _Init_thread_epoch + _Init_thread_footer _Init_thread_header _tls_index + ) + + if(CMAKE_SIZEOF_VOID_P EQUAL 8) + # new/delete variants needed when linking to static msvc runtime (esp. Debug) + set(ClangReplInterpreterTests_exports ${ClangReplInterpreterTests_exports} + ??2@YAPEAX_K@Z + ??3@YAXPEAX@Z + ??_U@YAPEAX_K@Z + ??_V@YAXPEAX@Z + ??3@YAXPEAX_K@Z + ) + else() + set(ClangReplInterpreterTests_exports ${ClangReplInterpreterTests_exports} + ??2@YAPAXI@Z + ??3@YAXPAX@Z + ??3@YAXPAXI@Z + ??_U@YAPAXI@Z + ??_V@YAXPAX@Z + ??_V@YAXPAXI@Z + ) + endif() + + # List to '/EXPORT:sym0 /EXPORT:sym1 /EXPORT:sym2 ...' + foreach(sym ${ClangReplInterpreterTests_exports}) + set(ClangReplInterpreterTests_link_str "${ClangReplInterpreterTests_link_str} /EXPORT:${sym}") + endforeach(sym ${ClangReplInterpreterTests_exports}) + + set_property(TARGET ClangReplInterpreterTests APPEND_STRING PROPERTY LINK_FLAGS ${ClangReplInterpreterTests_link_str}) + +endif(MSVC) diff --git a/clang/unittests/StaticAnalyzer/CallEventTest.cpp b/clang/unittests/StaticAnalyzer/CallEventTest.cpp index adbfe02a284d..7c4132788ca7 100644 --- a/clang/unittests/StaticAnalyzer/CallEventTest.cpp +++ b/clang/unittests/StaticAnalyzer/CallEventTest.cpp @@ -76,7 +76,7 @@ TEST(CXXDeallocatorCall, SimpleDestructor) { } )", Diags)); - EXPECT_EQ(Diags, "test.CXXDeallocator: NumArgs: 1\n"); + EXPECT_EQ(Diags, "test.CXXDeallocator: NumArgs: 2\n"); } } // namespace diff --git a/clang/www/cxx_status.html b/clang/www/cxx_status.html index a11bf9a06f9f..45416170b16e 100755 --- a/clang/www/cxx_status.html +++ b/clang/www/cxx_status.html @@ -1255,12 +1255,11 @@ version.

-(7): In Clang 3.7 and later, sized deallocation is only enabled -if the user passes the -fsized-deallocation flag. The user must -supply definitions of the sized deallocation functions, either by providing them -explicitly or by using a C++ standard library that does. libstdc++ -added these functions in version 5.0, and libc++ added them in -version 3.7. +(7): The user must supply definitions of the sized deallocation + functions, either by providing them explicitly or by using a C++ standard library + that does. libstdc++ added these functions in version 5.0, and + libc++ added them in version 3.7. The user can also use the + -fno-sized-deallocation option to disable sized deallocation.

diff --git a/libcxx/test/libcxx/language.support/support.dynamic/libcpp_deallocate.sh.cpp b/libcxx/test/libcxx/language.support/support.dynamic/libcpp_deallocate.sh.cpp index f94ceaf57dba..aa3ce210e363 100644 --- a/libcxx/test/libcxx/language.support/support.dynamic/libcpp_deallocate.sh.cpp +++ b/libcxx/test/libcxx/language.support/support.dynamic/libcpp_deallocate.sh.cpp @@ -21,6 +21,9 @@ // GCC doesn't support the aligned-allocation flags. // XFAIL: gcc +// TODO(mordante) fix this test after updating clang in Docker +// UNSUPPORTED: clang-15, clang-16, clang-17, clang-18, clang-19 + // RUN: %{build} -faligned-allocation -fsized-deallocation // RUN: %{run} // RUN: %{build} -faligned-allocation -fno-sized-deallocation -DNO_SIZE diff --git a/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.array/sized_delete_array14.pass.cpp b/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.array/sized_delete_array14.pass.cpp index 21663cdf956d..0241e7cefcac 100644 --- a/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.array/sized_delete_array14.pass.cpp +++ b/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.array/sized_delete_array14.pass.cpp @@ -8,11 +8,11 @@ // test sized operator delete[] replacement. +// TODO(mordante) fix this test after updating clang in Docker +// UNSUPPORTED: clang-15, clang-16, clang-17, clang-18, clang-19 // UNSUPPORTED: sanitizer-new-delete, c++03, c++11 - -// NOTE: Clang does not enable sized-deallocation in C++14 and beyond by -// default. It is only enabled when -fsized-deallocation is given. -// XFAIL: clang, apple-clang +// XFAIL: apple-clang +// XFAIL: using-built-library-before-llvm-11 #include #include diff --git a/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.single/sized_delete14.pass.cpp b/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.single/sized_delete14.pass.cpp index a8701ce7a86c..2ab691618ea4 100644 --- a/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.single/sized_delete14.pass.cpp +++ b/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.single/sized_delete14.pass.cpp @@ -8,11 +8,11 @@ // test sized operator delete replacement. +// TODO(mordante) fix this test after updating clang in Docker +// UNSUPPORTED: clang-15, clang-16, clang-17, clang-18, clang-19 // UNSUPPORTED: sanitizer-new-delete, c++03, c++11 - -// NOTE: Clang does not enable sized-deallocation in C++14 and beyond by -// default. It is only enabled when -fsized-deallocation is given. -// XFAIL: clang, apple-clang +// XFAIL: apple-clang +// XFAIL: using-built-library-before-llvm-11 #include #include -- GitLab From 7370b109b44a187e55d032d9628e41a7b94c3914 Mon Sep 17 00:00:00 2001 From: csstormq Date: Wed, 22 May 2024 13:16:03 +0800 Subject: [PATCH 070/452] Revert "[llvm][ScheduleDAG] SUnit::biasCriticalPath() does not find the critical path consistently (#92368)" (#92992) This reverts commit f0d1ae83b046ff0eeffc72a103f7c8b01ad33787. This commit breaks tests: http://45.33.8.238/linux/138572/step_11.txt --- llvm/lib/CodeGen/ScheduleDAG.cpp | 4 +- .../test/CodeGen/X86/misched-critical-path.ll | 240 ------------------ 2 files changed, 1 insertion(+), 243 deletions(-) delete mode 100644 llvm/test/CodeGen/X86/misched-critical-path.ll diff --git a/llvm/lib/CodeGen/ScheduleDAG.cpp b/llvm/lib/CodeGen/ScheduleDAG.cpp index 8d9a5041fc2f..de8e6f63794d 100644 --- a/llvm/lib/CodeGen/ScheduleDAG.cpp +++ b/llvm/lib/CodeGen/ScheduleDAG.cpp @@ -331,10 +331,8 @@ void SUnit::biasCriticalPath() { unsigned MaxDepth = BestI->getSUnit()->getDepth(); for (SUnit::pred_iterator I = std::next(BestI), E = Preds.end(); I != E; ++I) { - if (I->getKind() == SDep::Data && I->getSUnit()->getDepth() > MaxDepth) { - MaxDepth = I->getSUnit()->getDepth(); + if (I->getKind() == SDep::Data && I->getSUnit()->getDepth() > MaxDepth) BestI = I; - } } if (BestI != Preds.begin()) std::swap(*Preds.begin(), *BestI); diff --git a/llvm/test/CodeGen/X86/misched-critical-path.ll b/llvm/test/CodeGen/X86/misched-critical-path.ll deleted file mode 100644 index 909692aca2b0..000000000000 --- a/llvm/test/CodeGen/X86/misched-critical-path.ll +++ /dev/null @@ -1,240 +0,0 @@ -; RUN: llc < %s -mtriple=x86_64-apple-darwin8 -misched-print-dags -o - 2>&1 > /dev/null | FileCheck %s - -target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128" - -@sc = common global i8 0 -@uc = common global i8 0 -@ss = common global i16 0 -@us = common global i16 0 -@si = common global i32 0 -@ui = common global i32 0 -@sl = common global i64 0 -@ul = common global i64 0 -@sll = common global i64 0 -@ull = common global i64 0 - -; Regression Test for PR92368. -; -; CHECK: SU(75): CMP8rr %49:gr8, %48:gr8, implicit-def $eflags -; CHECK: Predecessors: -; CHECK-NEXT: SU(73): Data Latency=0 Reg=%49 -; CHECK-NEXT: SU(74): Out Latency=0 -; CHECK-NEXT: SU(72): Out Latency=0 -; CHECK-NEXT: SU(70): Data Latency=4 Reg=%48 -define void @misched_bug() nounwind { -entry: - %0 = load i8, i8* @sc, align 1 - %1 = zext i8 %0 to i32 - %2 = load i8, i8* @uc, align 1 - %3 = zext i8 %2 to i32 - %4 = trunc i32 %3 to i8 - %5 = trunc i32 %1 to i8 - %pair6 = cmpxchg i8* @sc, i8 %4, i8 %5 monotonic monotonic - %6 = extractvalue { i8, i1 } %pair6, 0 - store i8 %6, i8* @sc, align 1 - %7 = load i8, i8* @sc, align 1 - %8 = zext i8 %7 to i32 - %9 = load i8, i8* @uc, align 1 - %10 = zext i8 %9 to i32 - %11 = trunc i32 %10 to i8 - %12 = trunc i32 %8 to i8 - %pair13 = cmpxchg i8* @uc, i8 %11, i8 %12 monotonic monotonic - %13 = extractvalue { i8, i1 } %pair13, 0 - store i8 %13, i8* @uc, align 1 - %14 = load i8, i8* @sc, align 1 - %15 = sext i8 %14 to i16 - %16 = zext i16 %15 to i32 - %17 = load i8, i8* @uc, align 1 - %18 = zext i8 %17 to i32 - %19 = bitcast i8* bitcast (i16* @ss to i8*) to i16* - %20 = trunc i32 %18 to i16 - %21 = trunc i32 %16 to i16 - %pair22 = cmpxchg i16* %19, i16 %20, i16 %21 monotonic monotonic - %22 = extractvalue { i16, i1 } %pair22, 0 - store i16 %22, i16* @ss, align 2 - %23 = load i8, i8* @sc, align 1 - %24 = sext i8 %23 to i16 - %25 = zext i16 %24 to i32 - %26 = load i8, i8* @uc, align 1 - %27 = zext i8 %26 to i32 - %28 = bitcast i8* bitcast (i16* @us to i8*) to i16* - %29 = trunc i32 %27 to i16 - %30 = trunc i32 %25 to i16 - %pair31 = cmpxchg i16* %28, i16 %29, i16 %30 monotonic monotonic - %31 = extractvalue { i16, i1 } %pair31, 0 - store i16 %31, i16* @us, align 2 - %32 = load i8, i8* @sc, align 1 - %33 = sext i8 %32 to i32 - %34 = load i8, i8* @uc, align 1 - %35 = zext i8 %34 to i32 - %36 = bitcast i8* bitcast (i32* @si to i8*) to i32* - %pair37 = cmpxchg i32* %36, i32 %35, i32 %33 monotonic monotonic - %37 = extractvalue { i32, i1 } %pair37, 0 - store i32 %37, i32* @si, align 4 - %38 = load i8, i8* @sc, align 1 - %39 = sext i8 %38 to i32 - %40 = load i8, i8* @uc, align 1 - %41 = zext i8 %40 to i32 - %42 = bitcast i8* bitcast (i32* @ui to i8*) to i32* - %pair43 = cmpxchg i32* %42, i32 %41, i32 %39 monotonic monotonic - %43 = extractvalue { i32, i1 } %pair43, 0 - store i32 %43, i32* @ui, align 4 - %44 = load i8, i8* @sc, align 1 - %45 = sext i8 %44 to i64 - %46 = load i8, i8* @uc, align 1 - %47 = zext i8 %46 to i64 - %48 = bitcast i8* bitcast (i64* @sl to i8*) to i64* - %pair49 = cmpxchg i64* %48, i64 %47, i64 %45 monotonic monotonic - %49 = extractvalue { i64, i1 } %pair49, 0 - store i64 %49, i64* @sl, align 8 - %50 = load i8, i8* @sc, align 1 - %51 = sext i8 %50 to i64 - %52 = load i8, i8* @uc, align 1 - %53 = zext i8 %52 to i64 - %54 = bitcast i8* bitcast (i64* @ul to i8*) to i64* - %pair55 = cmpxchg i64* %54, i64 %53, i64 %51 monotonic monotonic - %55 = extractvalue { i64, i1 } %pair55, 0 - store i64 %55, i64* @ul, align 8 - %56 = load i8, i8* @sc, align 1 - %57 = sext i8 %56 to i64 - %58 = load i8, i8* @uc, align 1 - %59 = zext i8 %58 to i64 - %60 = bitcast i8* bitcast (i64* @sll to i8*) to i64* - %pair61 = cmpxchg i64* %60, i64 %59, i64 %57 monotonic monotonic - %61 = extractvalue { i64, i1 } %pair61, 0 - store i64 %61, i64* @sll, align 8 - %62 = load i8, i8* @sc, align 1 - %63 = sext i8 %62 to i64 - %64 = load i8, i8* @uc, align 1 - %65 = zext i8 %64 to i64 - %66 = bitcast i8* bitcast (i64* @ull to i8*) to i64* - %pair67 = cmpxchg i64* %66, i64 %65, i64 %63 monotonic monotonic - %67 = extractvalue { i64, i1 } %pair67, 0 - store i64 %67, i64* @ull, align 8 - %68 = load i8, i8* @sc, align 1 - %69 = zext i8 %68 to i32 - %70 = load i8, i8* @uc, align 1 - %71 = zext i8 %70 to i32 - %72 = trunc i32 %71 to i8 - %73 = trunc i32 %69 to i8 - %pair74 = cmpxchg i8* @sc, i8 %72, i8 %73 monotonic monotonic - %74 = extractvalue { i8, i1 } %pair74, 0 - %75 = icmp eq i8 %74, %72 - %76 = zext i1 %75 to i8 - %77 = zext i8 %76 to i32 - store i32 %77, i32* @ui, align 4 - %78 = load i8, i8* @sc, align 1 - %79 = zext i8 %78 to i32 - %80 = load i8, i8* @uc, align 1 - %81 = zext i8 %80 to i32 - %82 = trunc i32 %81 to i8 - %83 = trunc i32 %79 to i8 - %pair84 = cmpxchg i8* @uc, i8 %82, i8 %83 monotonic monotonic - %84 = extractvalue { i8, i1 } %pair84, 0 - %85 = icmp eq i8 %84, %82 - %86 = zext i1 %85 to i8 - %87 = zext i8 %86 to i32 - store i32 %87, i32* @ui, align 4 - %88 = load i8, i8* @sc, align 1 - %89 = sext i8 %88 to i16 - %90 = zext i16 %89 to i32 - %91 = load i8, i8* @uc, align 1 - %92 = zext i8 %91 to i32 - %93 = trunc i32 %92 to i8 - %94 = trunc i32 %90 to i8 - %pair95 = cmpxchg i8* bitcast (i16* @ss to i8*), i8 %93, i8 %94 monotonic monotonic - %95 = extractvalue { i8, i1 } %pair95, 0 - %96 = icmp eq i8 %95, %93 - %97 = zext i1 %96 to i8 - %98 = zext i8 %97 to i32 - store i32 %98, i32* @ui, align 4 - %99 = load i8, i8* @sc, align 1 - %100 = sext i8 %99 to i16 - %101 = zext i16 %100 to i32 - %102 = load i8, i8* @uc, align 1 - %103 = zext i8 %102 to i32 - %104 = trunc i32 %103 to i8 - %105 = trunc i32 %101 to i8 - %pair106 = cmpxchg i8* bitcast (i16* @us to i8*), i8 %104, i8 %105 monotonic monotonic - %106 = extractvalue { i8, i1 } %pair106, 0 - %107 = icmp eq i8 %106, %104 - %108 = zext i1 %107 to i8 - %109 = zext i8 %108 to i32 - store i32 %109, i32* @ui, align 4 - %110 = load i8, i8* @sc, align 1 - %111 = sext i8 %110 to i32 - %112 = load i8, i8* @uc, align 1 - %113 = zext i8 %112 to i32 - %114 = trunc i32 %113 to i8 - %115 = trunc i32 %111 to i8 - %pair116 = cmpxchg i8* bitcast (i32* @si to i8*), i8 %114, i8 %115 monotonic monotonic - %116 = extractvalue { i8, i1 } %pair116, 0 - %117 = icmp eq i8 %116, %114 - %118 = zext i1 %117 to i8 - %119 = zext i8 %118 to i32 - store i32 %119, i32* @ui, align 4 - %120 = load i8, i8* @sc, align 1 - %121 = sext i8 %120 to i32 - %122 = load i8, i8* @uc, align 1 - %123 = zext i8 %122 to i32 - %124 = trunc i32 %123 to i8 - %125 = trunc i32 %121 to i8 - %pair126 = cmpxchg i8* bitcast (i32* @ui to i8*), i8 %124, i8 %125 monotonic monotonic - %126 = extractvalue { i8, i1 } %pair126, 0 - %127 = icmp eq i8 %126, %124 - %128 = zext i1 %127 to i8 - %129 = zext i8 %128 to i32 - store i32 %129, i32* @ui, align 4 - %130 = load i8, i8* @sc, align 1 - %131 = sext i8 %130 to i64 - %132 = load i8, i8* @uc, align 1 - %133 = zext i8 %132 to i64 - %134 = trunc i64 %133 to i8 - %135 = trunc i64 %131 to i8 - %pair136 = cmpxchg i8* bitcast (i64* @sl to i8*), i8 %134, i8 %135 monotonic monotonic - %136 = extractvalue { i8, i1 } %pair136, 0 - %137 = icmp eq i8 %136, %134 - %138 = zext i1 %137 to i8 - %139 = zext i8 %138 to i32 - store i32 %139, i32* @ui, align 4 - %140 = load i8, i8* @sc, align 1 - %141 = sext i8 %140 to i64 - %142 = load i8, i8* @uc, align 1 - %143 = zext i8 %142 to i64 - %144 = trunc i64 %143 to i8 - %145 = trunc i64 %141 to i8 - %pair146 = cmpxchg i8* bitcast (i64* @ul to i8*), i8 %144, i8 %145 monotonic monotonic - %146 = extractvalue { i8, i1 } %pair146, 0 - %147 = icmp eq i8 %146, %144 - %148 = zext i1 %147 to i8 - %149 = zext i8 %148 to i32 - store i32 %149, i32* @ui, align 4 - %150 = load i8, i8* @sc, align 1 - %151 = sext i8 %150 to i64 - %152 = load i8, i8* @uc, align 1 - %153 = zext i8 %152 to i64 - %154 = trunc i64 %153 to i8 - %155 = trunc i64 %151 to i8 - %pair156 = cmpxchg i8* bitcast (i64* @sll to i8*), i8 %154, i8 %155 monotonic monotonic - %156 = extractvalue { i8, i1 } %pair156, 0 - %157 = icmp eq i8 %156, %154 - %158 = zext i1 %157 to i8 - %159 = zext i8 %158 to i32 - store i32 %159, i32* @ui, align 4 - %160 = load i8, i8* @sc, align 1 - %161 = sext i8 %160 to i64 - %162 = load i8, i8* @uc, align 1 - %163 = zext i8 %162 to i64 - %164 = trunc i64 %163 to i8 - %165 = trunc i64 %161 to i8 - %pair166 = cmpxchg i8* bitcast (i64* @ull to i8*), i8 %164, i8 %165 monotonic monotonic - %166 = extractvalue { i8, i1 } %pair166, 0 - %167 = icmp eq i8 %166, %164 - %168 = zext i1 %167 to i8 - %169 = zext i8 %168 to i32 - store i32 %169, i32* @ui, align 4 - br label %return - -return: ; preds = %entry - ret void -} -- GitLab From 108575f02ea9927009ed81231474d3a6f053602f Mon Sep 17 00:00:00 2001 From: Nikita Popov Date: Wed, 22 May 2024 07:40:08 +0200 Subject: [PATCH 071/452] [IR] Avoid creating icmp/fcmp constant expressions (#92885) Do not create icmp/fcmp constant expressions in IRBuilder etc anymore, i.e. treat them as "undesirable". This is in preparation for removing them entirely. Part of: https://discourse.llvm.org/t/rfc-remove-most-constant-expressions/63179 --- clang/test/Analysis/builtin_signbit.cpp | 36 +++--- .../catch-nullptr-and-nonzero-offset.c | 62 +++++++---- clang/test/CodeGen/constantexpr-fneg.c | 3 +- clang/test/CodeGenCXX/cxx11-thread-local.cpp | 20 ++-- .../test/CodeGenCXX/ubsan-nullability-arg.cpp | 3 +- clang/test/CodeGenCXX/weak-external.cpp | 15 ++- clang/test/Driver/linker-wrapper-image.c | 98 +++++++++-------- clang/test/OpenMP/threadprivate_codegen.cpp | 104 ++++++++++-------- llvm/include/llvm/Analysis/TargetFolder.h | 2 +- llvm/include/llvm/IR/ConstantFolder.h | 2 +- llvm/lib/Analysis/ConstantFolding.cpp | 2 +- llvm/lib/IR/ConstantFold.cpp | 13 ++- llvm/test/Assembler/ConstantExprFold.ll | 4 +- llvm/test/Assembler/ConstantExprNoFold.ll | 4 +- llvm/test/Assembler/vector-cmp.ll | 2 +- .../AMDGPU/lower-ctor-dtor-constexpr-alias.ll | 3 +- llvm/test/CodeGen/AMDGPU/lower-ctor-dtor.ll | 3 +- .../AMDGPU/lower-multiple-ctor-dtor.ll | 3 +- .../MemorySanitizer/check-constant-shadow.ll | 3 +- .../SanitizerBinaryMetadata/atomics.ll | 12 +- .../Transforms/Attributor/value-simplify.ll | 7 +- .../binop-select-cast-of-select-cond.ll | 2 +- .../constant-fold-address-space-pointer.ll | 6 +- .../Transforms/InstCombine/getelementptr.ll | 3 +- ...hoist-xor-by-constant-from-xor-by-value.ll | 3 +- llvm/test/Transforms/InstCombine/pr33453.ll | 2 +- llvm/test/Transforms/InstCombine/pr83947.ll | 4 +- llvm/test/Transforms/InstCombine/rem.ll | 4 +- .../Transforms/InstCombine/select-and-or.ll | 4 +- .../InstCombine/select-safe-transforms.ll | 4 +- .../InstSimplify/ConstProp/bitcast.ll | 9 +- .../InstSimplify/ConstProp/icmp-global.ll | 54 ++++++--- .../InstSimplify/bitcast-vector-fold.ll | 3 +- llvm/test/Transforms/InstSimplify/compare.ll | 6 +- .../Transforms/InstSimplify/past-the-end.ll | 6 +- .../JumpThreading/constant-fold-status.ll | 3 +- .../LowerTypeTests/cfi-direct-call1.ll | 10 +- .../LowerTypeTests/function-weak.ll | 74 +++++++------ .../test/Transforms/SCCP/conditions-ranges.ll | 9 +- .../phi-to-select-constexpr-icmp.ll | 2 +- 40 files changed, 353 insertions(+), 256 deletions(-) diff --git a/clang/test/Analysis/builtin_signbit.cpp b/clang/test/Analysis/builtin_signbit.cpp index 57e6816ce280..be10f0950f69 100644 --- a/clang/test/Analysis/builtin_signbit.cpp +++ b/clang/test/Analysis/builtin_signbit.cpp @@ -84,28 +84,30 @@ long double ld = -1.0L; // CHECK-LE-LABEL: define dso_local void @_Z12test_signbitv( // CHECK-LE-SAME: ) #[[ATTR0:[0-9]+]] { // CHECK-LE-NEXT: entry: -// CHECK-LE-NEXT: [[FROMBOOL:%.*]] = zext i1 icmp slt (i64 trunc (i128 bitcast (ppc_fp128 0xM3FF00000000000000000000000000000 to i128) to i64), i64 0) to i8 +// CHECK-LE-NEXT: [[TMP0:%.*]] = icmp slt i64 trunc (i128 bitcast (ppc_fp128 0xM3FF00000000000000000000000000000 to i128) to i64), 0 +// CHECK-LE-NEXT: [[FROMBOOL:%.*]] = zext i1 [[TMP0]] to i8 // CHECK-LE-NEXT: store i8 [[FROMBOOL]], ptr @b, align 1 -// CHECK-LE-NEXT: [[TMP0:%.*]] = load ppc_fp128, ptr @ld, align 16 -// CHECK-LE-NEXT: [[TMP1:%.*]] = bitcast ppc_fp128 [[TMP0]] to i128 -// CHECK-LE-NEXT: [[TMP2:%.*]] = trunc i128 [[TMP1]] to i64 -// CHECK-LE-NEXT: [[TMP3:%.*]] = icmp slt i64 [[TMP2]], 0 -// CHECK-LE-NEXT: [[FROMBOOL1:%.*]] = zext i1 [[TMP3]] to i8 +// CHECK-LE-NEXT: [[TMP1:%.*]] = load ppc_fp128, ptr @ld, align 16 +// CHECK-LE-NEXT: [[TMP2:%.*]] = bitcast ppc_fp128 [[TMP1]] to i128 +// CHECK-LE-NEXT: [[TMP3:%.*]] = trunc i128 [[TMP2]] to i64 +// CHECK-LE-NEXT: [[TMP4:%.*]] = icmp slt i64 [[TMP3]], 0 +// CHECK-LE-NEXT: [[FROMBOOL1:%.*]] = zext i1 [[TMP4]] to i8 // CHECK-LE-NEXT: store i8 [[FROMBOOL1]], ptr @b, align 1 // CHECK-LE-NEXT: store i8 0, ptr @b, align 1 -// CHECK-LE-NEXT: [[TMP4:%.*]] = load double, ptr @d, align 8 -// CHECK-LE-NEXT: [[CONV:%.*]] = fptrunc double [[TMP4]] to float -// CHECK-LE-NEXT: [[TMP5:%.*]] = bitcast float [[CONV]] to i32 -// CHECK-LE-NEXT: [[TMP6:%.*]] = icmp slt i32 [[TMP5]], 0 -// CHECK-LE-NEXT: [[FROMBOOL2:%.*]] = zext i1 [[TMP6]] to i8 +// CHECK-LE-NEXT: [[TMP5:%.*]] = load double, ptr @d, align 8 +// CHECK-LE-NEXT: [[CONV:%.*]] = fptrunc double [[TMP5]] to float +// CHECK-LE-NEXT: [[TMP6:%.*]] = bitcast float [[CONV]] to i32 +// CHECK-LE-NEXT: [[TMP7:%.*]] = icmp slt i32 [[TMP6]], 0 +// CHECK-LE-NEXT: [[FROMBOOL2:%.*]] = zext i1 [[TMP7]] to i8 // CHECK-LE-NEXT: store i8 [[FROMBOOL2]], ptr @b, align 1 -// CHECK-LE-NEXT: [[FROMBOOL3:%.*]] = zext i1 icmp slt (i64 trunc (i128 bitcast (ppc_fp128 0xM3FF00000000000000000000000000000 to i128) to i64), i64 0) to i8 +// CHECK-LE-NEXT: [[TMP8:%.*]] = icmp slt i64 trunc (i128 bitcast (ppc_fp128 0xM3FF00000000000000000000000000000 to i128) to i64), 0 +// CHECK-LE-NEXT: [[FROMBOOL3:%.*]] = zext i1 [[TMP8]] to i8 // CHECK-LE-NEXT: store i8 [[FROMBOOL3]], ptr @b, align 1 -// CHECK-LE-NEXT: [[TMP7:%.*]] = load ppc_fp128, ptr @ld, align 16 -// CHECK-LE-NEXT: [[TMP8:%.*]] = bitcast ppc_fp128 [[TMP7]] to i128 -// CHECK-LE-NEXT: [[TMP9:%.*]] = trunc i128 [[TMP8]] to i64 -// CHECK-LE-NEXT: [[TMP10:%.*]] = icmp slt i64 [[TMP9]], 0 -// CHECK-LE-NEXT: [[FROMBOOL4:%.*]] = zext i1 [[TMP10]] to i8 +// CHECK-LE-NEXT: [[TMP9:%.*]] = load ppc_fp128, ptr @ld, align 16 +// CHECK-LE-NEXT: [[TMP10:%.*]] = bitcast ppc_fp128 [[TMP9]] to i128 +// CHECK-LE-NEXT: [[TMP11:%.*]] = trunc i128 [[TMP10]] to i64 +// CHECK-LE-NEXT: [[TMP12:%.*]] = icmp slt i64 [[TMP11]], 0 +// CHECK-LE-NEXT: [[FROMBOOL4:%.*]] = zext i1 [[TMP12]] to i8 // CHECK-LE-NEXT: store i8 [[FROMBOOL4]], ptr @b, align 1 // CHECK-LE-NEXT: ret void // diff --git a/clang/test/CodeGen/catch-nullptr-and-nonzero-offset.c b/clang/test/CodeGen/catch-nullptr-and-nonzero-offset.c index 015102940890..e93dbcb9f647 100644 --- a/clang/test/CodeGen/catch-nullptr-and-nonzero-offset.c +++ b/clang/test/CodeGen/catch-nullptr-and-nonzero-offset.c @@ -217,8 +217,10 @@ char *nullptr_zero(void) { char *nullptr_one_BAD(void) { // CHECK: define{{.*}} ptr @nullptr_one_BAD() // CHECK-NEXT: [[ENTRY:.*]]: - // CHECK-SANITIZE-C-NEXT: br i1 false, label %[[CONT:.*]], label %[[HANDLER_POINTER_OVERFLOW:[^,]+]],{{.*}} !nosanitize - // CHECK-SANITIZE-CPP-NEXT: br i1 icmp eq (i64 ptrtoint (ptr getelementptr inbounds (i8, ptr null, i64 1) to i64), i64 0), label %[[CONT:.*]], label %[[HANDLER_POINTER_OVERFLOW:[^,]+]],{{.*}} !nosanitize + // CHECK-SANITIZE-NEXT: %[[CMP:.*]] = icmp ne i64 ptrtoint (ptr getelementptr inbounds (i8, ptr null, i64 1) to i64), 0, !nosanitize + // CHECK-SANITIZE-C-NEXT: %[[COND:.*]] = and i1 false, %[[CMP]], !nosanitize + // CHECK-SANITIZE-CPP-NEXT: %[[COND:.*]] = icmp eq i1 false, %[[CMP]], !nosanitize + // CHECK-SANITIZE-NEXT: br i1 %[[COND]], label %[[CONT:.*]], label %[[HANDLER_POINTER_OVERFLOW:[^,]+]],{{.*}} !nosanitize // CHECK-SANITIZE: [[HANDLER_POINTER_OVERFLOW]]: // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_pointer_overflow_abort(ptr @[[LINE_700]], i64 0, i64 ptrtoint (ptr getelementptr inbounds (i8, ptr null, i64 1) to i64)) // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_pointer_overflow(ptr @[[LINE_700]], i64 0, i64 ptrtoint (ptr getelementptr inbounds (i8, ptr null, i64 1) to i64)) @@ -235,8 +237,10 @@ char *nullptr_one_BAD(void) { char *nullptr_allones_BAD(void) { // CHECK: define{{.*}} ptr @nullptr_allones_BAD() // CHECK-NEXT: [[ENTRY:.*]]: - // CHECK-SANITIZE-C-NEXT: br i1 false, label %[[CONT:.*]], label %[[HANDLER_POINTER_OVERFLOW:[^,]+]],{{.*}} !nosanitize - // CHECK-SANITIZE-CPP-NEXT: br i1 icmp eq (i64 ptrtoint (ptr getelementptr inbounds (i8, ptr null, i64 -1) to i64), i64 0), label %[[CONT:.*]], label %[[HANDLER_POINTER_OVERFLOW:[^,]+]],{{.*}} !nosanitize + // CHECK-SANITIZE-NEXT: %[[CMP:.*]] = icmp ne i64 ptrtoint (ptr getelementptr inbounds (i8, ptr null, i64 -1) to i64), 0, !nosanitize + // CHECK-SANITIZE-C-NEXT: %[[COND:.*]] = and i1 false, %[[CMP]], !nosanitize + // CHECK-SANITIZE-CPP-NEXT: %[[COND:.*]] = icmp eq i1 false, %[[CMP]], !nosanitize + // CHECK-SANITIZE-NEXT: br i1 %[[COND]], label %[[CONT:.*]], label %[[HANDLER_POINTER_OVERFLOW:[^,]+]],{{.*}} !nosanitize // CHECK-SANITIZE: [[HANDLER_POINTER_OVERFLOW]]: // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_pointer_overflow_abort(ptr @[[LINE_800]], i64 0, i64 ptrtoint (ptr getelementptr inbounds (i8, ptr null, i64 -1) to i64)) // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_pointer_overflow(ptr @[[LINE_800]], i64 0, i64 ptrtoint (ptr getelementptr inbounds (i8, ptr null, i64 -1) to i64)) @@ -264,9 +268,10 @@ char *one_var(unsigned long offset) { // CHECK-SANITIZE-NEXT: %[[OR_OV:.+]] = or i1 %[[COMPUTED_OFFSET_OVERFLOWED]], false, !nosanitize // CHECK-SANITIZE-NEXT: %[[COMPUTED_OFFSET:.*]] = extractvalue { i64, i1 } %[[COMPUTED_OFFSET_AGGREGATE]], 0, !nosanitize // CHECK-SANITIZE-NEXT: %[[COMPUTED_GEP:.*]] = add i64 1, %[[COMPUTED_OFFSET]], !nosanitize + // CHECK-SANITIZE-NEXT: %[[OTHER_IS_NOT_NULL:.*]] = icmp ne ptr inttoptr (i64 1 to ptr), null // CHECK-SANITIZE-NEXT: %[[COMPUTED_GEP_IS_NOT_NULL:.*]] = icmp ne i64 %[[COMPUTED_GEP]], 0, !nosanitize - // CHECK-SANITIZE-C-NEXT: %[[BOTH_POINTERS_ARE_NULL_OR_BOTH_ARE_NONNULL:.*]] = and i1 icmp ne (ptr inttoptr (i64 1 to ptr), ptr null), %[[COMPUTED_GEP_IS_NOT_NULL]], !nosanitize - // CHECK-SANITIZE-CPP-NEXT: %[[BOTH_POINTERS_ARE_NULL_OR_BOTH_ARE_NONNULL:.*]] = icmp eq i1 icmp ne (ptr inttoptr (i64 1 to ptr), ptr null), %[[COMPUTED_GEP_IS_NOT_NULL]], !nosanitize + // CHECK-SANITIZE-C-NEXT: %[[BOTH_POINTERS_ARE_NULL_OR_BOTH_ARE_NONNULL:.*]] = and i1 %[[OTHER_IS_NOT_NULL]], %[[COMPUTED_GEP_IS_NOT_NULL]], !nosanitize + // CHECK-SANITIZE-CPP-NEXT: %[[BOTH_POINTERS_ARE_NULL_OR_BOTH_ARE_NONNULL:.*]] = icmp eq i1 %[[OTHER_IS_NOT_NULL]], %[[COMPUTED_GEP_IS_NOT_NULL]], !nosanitize // CHECK-SANITIZE-NEXT: %[[COMPUTED_OFFSET_DID_NOT_OVERFLOW:.*]] = xor i1 %[[OR_OV]], true, !nosanitize // CHECK-SANITIZE-NEXT: %[[COMPUTED_GEP_IS_UGE_BASE:.*]] = icmp uge i64 %[[COMPUTED_GEP]], 1, !nosanitize // CHECK-SANITIZE-NEXT: %[[GEP_DID_NOT_OVERFLOW:.*]] = and i1 %[[COMPUTED_GEP_IS_UGE_BASE]], %[[COMPUTED_OFFSET_DID_NOT_OVERFLOW]], !nosanitize @@ -287,7 +292,9 @@ char *one_var(unsigned long offset) { char *one_zero(void) { // CHECK: define{{.*}} ptr @one_zero() // CHECK-NEXT: [[ENTRY:.*]]: - // CHECK-SANITIZE-C-NEXT: br i1 icmp ne (ptr inttoptr (i64 1 to ptr), ptr null), label %[[CONT:.*]], label %[[HANDLER_POINTER_OVERFLOW:[^,]+]],{{.*}} !nosanitize + // CHECK-SANITIZE-C-NEXT: %[[CMP:.*]] = icmp ne ptr inttoptr (i64 1 to ptr), null + // CHECK-SANITIZE-C-NEXT: %[[AND:.*]] = and i1 %[[CMP]], true + // CHECK-SANITIZE-C-NEXT: br i1 %[[AND]], label %[[CONT:.*]], label %[[HANDLER_POINTER_OVERFLOW:[^,]+]],{{.*}} !nosanitize // CHECK-SANITIZE-C: [[HANDLER_POINTER_OVERFLOW]]: // CHECK-SANITIZE-NORECOVER-C-NEXT: call void @__ubsan_handle_pointer_overflow_abort(ptr @[[LINE_1000]], i64 1, i64 1) // CHECK-SANITIZE-RECOVER-C-NEXT: call void @__ubsan_handle_pointer_overflow(ptr @[[LINE_1000]], i64 1, i64 1) @@ -304,9 +311,11 @@ char *one_zero(void) { char *one_one_OK(void) { // CHECK: define{{.*}} ptr @one_one_OK() // CHECK-NEXT: [[ENTRY:.*]]: - // CHECK-SANITIZE-C-NEXT: %[[AND:.*]] = and i1 icmp ne (ptr inttoptr (i64 1 to ptr), ptr null), icmp ne (i64 add (i64 sub (i64 ptrtoint (ptr getelementptr inbounds (i8, ptr inttoptr (i64 1 to ptr), i64 1) to i64), i64 1), i64 1), i64 0), !nosanitize - // CHECK-SANITIZE-C-NEXT: br i1 %[[AND]], label %[[CONT:.*]], label %[[HANDLER_POINTER_OVERFLOW:[^,]+]],{{.*}} !nosanitize - // CHECK-SANITIZE-CPP-NEXT: br i1 xor (i1 icmp eq (ptr inttoptr (i64 1 to ptr), ptr null), i1 icmp ne (i64 add (i64 sub (i64 ptrtoint (ptr getelementptr inbounds (i8, ptr inttoptr (i64 1 to ptr), i64 1) to i64), i64 1), i64 1), i64 0)), label %[[CONT:.*]], label %[[HANDLER_POINTER_OVERFLOW:[^,]+]],{{.*}} !nosanitize + // CHECK-SANITIZE-NEXT: %[[CMP1:.*]] = icmp ne ptr inttoptr (i64 1 to ptr), null, !nosanitize + // CHECK-SANITIZE-NEXT: %[[CMP2:.*]] = icmp ne i64 add (i64 sub (i64 ptrtoint (ptr getelementptr inbounds (i8, ptr inttoptr (i64 1 to ptr), i64 1) to i64), i64 1), i64 1), 0, !nosanitize + // CHECK-SANITIZE-C-NEXT: %[[COND:.*]] = and i1 %[[CMP1]], %[[CMP2]], !nosanitize + // CHECK-SANITIZE-CPP-NEXT: %[[COND:.*]] = icmp eq i1 %[[CMP1]], %[[CMP2]], !nosanitize + // CHECK-SANITIZE-NEXT: br i1 %[[COND]], label %[[CONT:.*]], label %[[HANDLER_POINTER_OVERFLOW:[^,]+]],{{.*}} !nosanitize // CHECK-SANITIZE: [[HANDLER_POINTER_OVERFLOW]]: // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_pointer_overflow_abort(ptr @[[LINE_1100]], i64 1, i64 add (i64 sub (i64 ptrtoint (ptr getelementptr inbounds (i8, ptr inttoptr (i64 1 to ptr), i64 1) to i64), i64 1), i64 1)) // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_pointer_overflow(ptr @[[LINE_1100]], i64 1, i64 add (i64 sub (i64 ptrtoint (ptr getelementptr inbounds (i8, ptr inttoptr (i64 1 to ptr), i64 1) to i64), i64 1), i64 1)) @@ -323,9 +332,11 @@ char *one_one_OK(void) { char *one_allones_BAD(void) { // CHECK: define{{.*}} ptr @one_allones_BAD() // CHECK-NEXT: [[ENTRY:.*]]: - // CHECK-SANITIZE-C-NEXT: %[[AND:.*]] = and i1 icmp ne (ptr inttoptr (i64 1 to ptr), ptr null), icmp ne (i64 add (i64 sub (i64 ptrtoint (ptr getelementptr inbounds (i8, ptr inttoptr (i64 1 to ptr), i64 -1) to i64), i64 1), i64 1), i64 0), !nosanitize - // CHECK-SANITIZE-C-NEXT: br i1 %[[AND]], label %[[CONT:.*]], label %[[HANDLER_POINTER_OVERFLOW:[^,]+]],{{.*}} !nosanitize - // CHECK-SANITIZE-CPP-NEXT: br i1 xor (i1 icmp eq (ptr inttoptr (i64 1 to ptr), ptr null), i1 icmp ne (i64 add (i64 sub (i64 ptrtoint (ptr getelementptr inbounds (i8, ptr inttoptr (i64 1 to ptr), i64 -1) to i64), i64 1), i64 1), i64 0)), label %[[CONT:.*]], label %[[HANDLER_POINTER_OVERFLOW:[^,]+]],{{.*}} !nosanitize + // CHECK-SANITIZE-NEXT: %[[CMP1:.*]] = icmp ne ptr inttoptr (i64 1 to ptr), null, !nosanitize + // CHECK-SANITIZE-NEXT: %[[CMP2:.*]] = icmp ne i64 add (i64 sub (i64 ptrtoint (ptr getelementptr inbounds (i8, ptr inttoptr (i64 1 to ptr), i64 -1) to i64), i64 1), i64 1), 0, !nosanitize + // CHECK-SANITIZE-C-NEXT: %[[COND:.*]] = and i1 %[[CMP1]], %[[CMP2]], !nosanitize + // CHECK-SANITIZE-CPP-NEXT: %[[COND:.*]] = icmp eq i1 %[[CMP1]], %[[CMP2]], !nosanitize + // CHECK-SANITIZE-NEXT: br i1 %[[COND]], label %[[CONT:.*]], label %[[HANDLER_POINTER_OVERFLOW:[^,]+]],{{.*}} !nosanitize // CHECK-SANITIZE: [[HANDLER_POINTER_OVERFLOW]]: // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_pointer_overflow_abort(ptr @[[LINE_1200]], i64 1, i64 add (i64 sub (i64 ptrtoint (ptr getelementptr inbounds (i8, ptr inttoptr (i64 1 to ptr), i64 -1) to i64), i64 1), i64 1)) // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_pointer_overflow(ptr @[[LINE_1200]], i64 1, i64 add (i64 sub (i64 ptrtoint (ptr getelementptr inbounds (i8, ptr inttoptr (i64 1 to ptr), i64 -1) to i64), i64 1), i64 1)) @@ -353,9 +364,10 @@ char *allones_var(unsigned long offset) { // CHECK-SANITIZE-NEXT: %[[OR_OV:.+]] = or i1 %[[COMPUTED_OFFSET_OVERFLOWED]], false, !nosanitize // CHECK-SANITIZE-NEXT: %[[COMPUTED_OFFSET:.*]] = extractvalue { i64, i1 } %[[COMPUTED_OFFSET_AGGREGATE]], 0, !nosanitize // CHECK-SANITIZE-NEXT: %[[COMPUTED_GEP:.*]] = add i64 -1, %[[COMPUTED_OFFSET]], !nosanitize + // CHECK-SANITIZE-NEXT: %[[OTHER_IS_NOT_NULL:.*]] = icmp ne ptr inttoptr (i64 -1 to ptr), null, !nosanitize // CHECK-SANITIZE-NEXT: %[[COMPUTED_GEP_IS_NOT_NULL:.*]] = icmp ne i64 %[[COMPUTED_GEP]], 0, !nosanitize - // CHECK-SANITIZE-C-NEXT: %[[BOTH_POINTERS_ARE_NULL_OR_BOTH_ARE_NONNULL:.*]] = and i1 icmp ne (ptr inttoptr (i64 -1 to ptr), ptr null), %[[COMPUTED_GEP_IS_NOT_NULL]], !nosanitize - // CHECK-SANITIZE-CPP-NEXT: %[[BOTH_POINTERS_ARE_NULL_OR_BOTH_ARE_NONNULL:.*]] = icmp eq i1 icmp ne (ptr inttoptr (i64 -1 to ptr), ptr null), %[[COMPUTED_GEP_IS_NOT_NULL]], !nosanitize + // CHECK-SANITIZE-C-NEXT: %[[BOTH_POINTERS_ARE_NULL_OR_BOTH_ARE_NONNULL:.*]] = and i1 %[[OTHER_IS_NOT_NULL]], %[[COMPUTED_GEP_IS_NOT_NULL]], !nosanitize + // CHECK-SANITIZE-CPP-NEXT: %[[BOTH_POINTERS_ARE_NULL_OR_BOTH_ARE_NONNULL:.*]] = icmp eq i1 %[[OTHER_IS_NOT_NULL]], %[[COMPUTED_GEP_IS_NOT_NULL]], !nosanitize // CHECK-SANITIZE-NEXT: %[[COMPUTED_OFFSET_DID_NOT_OVERFLOW:.*]] = xor i1 %[[OR_OV]], true, !nosanitize // CHECK-SANITIZE-NEXT: %[[COMPUTED_GEP_IS_UGE_BASE:.*]] = icmp uge i64 %[[COMPUTED_GEP]], -1, !nosanitize // CHECK-SANITIZE-NEXT: %[[GEP_DID_NOT_OVERFLOW:.*]] = and i1 %[[COMPUTED_GEP_IS_UGE_BASE]], %[[COMPUTED_OFFSET_DID_NOT_OVERFLOW]], !nosanitize @@ -376,7 +388,9 @@ char *allones_var(unsigned long offset) { char *allones_zero_OK(void) { // CHECK: define{{.*}} ptr @allones_zero_OK() // CHECK-NEXT: [[ENTRY:.*]]: - // CHECK-SANITIZE-C-NEXT: br i1 icmp ne (ptr inttoptr (i64 -1 to ptr), ptr null), label %[[CONT:.*]], label %[[HANDLER_POINTER_OVERFLOW:[^,]+]],{{.*}} !nosanitize + // CHECK-SANITIZE-C-NEXT: %[[CMP:.*]] = icmp ne ptr inttoptr (i64 -1 to ptr), null, !nosanitize + // CHECK-SANITIZE-C-NEXT: %[[AND:.*]] = and i1 %[[CMP]], true, !nosanitize + // CHECK-SANITIZE-C-NEXT: br i1 %[[AND]], label %[[CONT:.*]], label %[[HANDLER_POINTER_OVERFLOW:[^,]+]],{{.*}} !nosanitize // CHECK-SANITIZE-C: [[HANDLER_POINTER_OVERFLOW]]: // CHECK-SANITIZE-NORECOVER-C-NEXT: call void @__ubsan_handle_pointer_overflow_abort(ptr @[[LINE_1400]], i64 -1, i64 -1) // CHECK-SANITIZE-RECOVER-C-NEXT: call void @__ubsan_handle_pointer_overflow(ptr @[[LINE_1400]], i64 -1, i64 -1) @@ -393,9 +407,11 @@ char *allones_zero_OK(void) { char *allones_one_BAD(void) { // CHECK: define{{.*}} ptr @allones_one_BAD() // CHECK-NEXT: [[ENTRY:.*]]: - // CHECK-SANITIZE-C-NEXT: %[[AND:.*]] = and i1 icmp ne (ptr inttoptr (i64 -1 to ptr), ptr null), icmp ne (i64 add (i64 sub (i64 ptrtoint (ptr getelementptr inbounds (i8, ptr inttoptr (i64 -1 to ptr), i64 1) to i64), i64 -1), i64 -1), i64 0), !nosanitize - // CHECK-SANITIZE-C-NEXT: br i1 %[[AND]], label %[[CONT:.*]], label %[[HANDLER_POINTER_OVERFLOW:[^,]+]],{{.*}} !nosanitize - // CHECK-SANITIZE-CPP-NEXT: br i1 xor (i1 icmp eq (ptr inttoptr (i64 -1 to ptr), ptr null), i1 icmp ne (i64 add (i64 sub (i64 ptrtoint (ptr getelementptr inbounds (i8, ptr inttoptr (i64 -1 to ptr), i64 1) to i64), i64 -1), i64 -1), i64 0)), label %[[CONT:.*]], label %[[HANDLER_POINTER_OVERFLOW:[^,]+]],{{.*}} !nosanitize + // CHECK-SANITIZE-NEXT: %[[CMP1:.*]] = icmp ne ptr inttoptr (i64 -1 to ptr), null, !nosanitize + // CHECK-SANITIZE-NEXT: %[[CMP2:.*]] = icmp ne i64 add (i64 sub (i64 ptrtoint (ptr getelementptr inbounds (i8, ptr inttoptr (i64 -1 to ptr), i64 1) to i64), i64 -1), i64 -1), 0, !nosanitize + // CHECK-SANITIZE-C-NEXT: %[[COND:.*]] = and i1 %[[CMP1]], %[[CMP2]], !nosanitize + // CHECK-SANITIZE-CPP-NEXT: %[[COND:.*]] = icmp eq i1 %[[CMP1]], %[[CMP2]], !nosanitize + // CHECK-SANITIZE-NEXT: br i1 %[[COND]], label %[[CONT:.*]], label %[[HANDLER_POINTER_OVERFLOW:[^,]+]],{{.*}} !nosanitize // CHECK-SANITIZE: [[HANDLER_POINTER_OVERFLOW]]: // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_pointer_overflow_abort(ptr @[[LINE_1500]], i64 -1, i64 add (i64 sub (i64 ptrtoint (ptr getelementptr inbounds (i8, ptr inttoptr (i64 -1 to ptr), i64 1) to i64), i64 -1), i64 -1)) // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_pointer_overflow(ptr @[[LINE_1500]], i64 -1, i64 add (i64 sub (i64 ptrtoint (ptr getelementptr inbounds (i8, ptr inttoptr (i64 -1 to ptr), i64 1) to i64), i64 -1), i64 -1)) @@ -412,9 +428,11 @@ char *allones_one_BAD(void) { char *allones_allones_OK(void) { // CHECK: define{{.*}} ptr @allones_allones_OK() // CHECK-NEXT: [[ENTRY:.*]]: - // CHECK-SANITIZE-C-NEXT: %[[AND:.*]] = and i1 icmp ne (ptr inttoptr (i64 -1 to ptr), ptr null), icmp ne (i64 add (i64 sub (i64 ptrtoint (ptr getelementptr inbounds (i8, ptr inttoptr (i64 -1 to ptr), i64 -1) to i64), i64 -1), i64 -1), i64 0), !nosanitize - // CHECK-SANITIZE-C-NEXT: br i1 %[[AND]], label %[[CONT:.*]], label %[[HANDLER_POINTER_OVERFLOW:[^,]+]],{{.*}} !nosanitize - // CHECK-SANITIZE-CPP-NEXT: br i1 xor (i1 icmp eq (ptr inttoptr (i64 -1 to ptr), ptr null), i1 icmp ne (i64 add (i64 sub (i64 ptrtoint (ptr getelementptr inbounds (i8, ptr inttoptr (i64 -1 to ptr), i64 -1) to i64), i64 -1), i64 -1), i64 0)), label %[[CONT:.*]], label %[[HANDLER_POINTER_OVERFLOW:[^,]+]],{{.*}} !nosanitize + // CHECK-SANITIZE-NEXT: %[[CMP1:.*]] = icmp ne ptr inttoptr (i64 -1 to ptr), null, !nosanitize + // CHECK-SANITIZE-NEXT: %[[CMP2:.*]] = icmp ne i64 add (i64 sub (i64 ptrtoint (ptr getelementptr inbounds (i8, ptr inttoptr (i64 -1 to ptr), i64 -1) to i64), i64 -1), i64 -1), 0, !nosanitize + // CHECK-SANITIZE-C-NEXT: %[[COND:.*]] = and i1 %[[CMP1]], %[[CMP2]], !nosanitize + // CHECK-SANITIZE-CPP-NEXT: %[[COND:.*]] = icmp eq i1 %[[CMP1]], %[[CMP2]], !nosanitize + // CHECK-SANITIZE-NEXT: br i1 %[[COND]], label %[[CONT:.*]], label %[[HANDLER_POINTER_OVERFLOW:[^,]+]],{{.*}} !nosanitize // CHECK-SANITIZE: [[HANDLER_POINTER_OVERFLOW]]: // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_pointer_overflow_abort(ptr @[[LINE_1600]], i64 -1, i64 add (i64 sub (i64 ptrtoint (ptr getelementptr inbounds (i8, ptr inttoptr (i64 -1 to ptr), i64 -1) to i64), i64 -1), i64 -1)) // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_pointer_overflow(ptr @[[LINE_1600]], i64 -1, i64 add (i64 sub (i64 ptrtoint (ptr getelementptr inbounds (i8, ptr inttoptr (i64 -1 to ptr), i64 -1) to i64), i64 -1), i64 -1)) diff --git a/clang/test/CodeGen/constantexpr-fneg.c b/clang/test/CodeGen/constantexpr-fneg.c index 3cd4db34f61a..fb7a3d1a6953 100644 --- a/clang/test/CodeGen/constantexpr-fneg.c +++ b/clang/test/CodeGen/constantexpr-fneg.c @@ -8,7 +8,8 @@ // CHECK: entry: // CHECK-NEXT: %retval = alloca i32 // CHECK-NEXT: store i32 0, ptr %retval -// CHECK-NEXT: [[ZEXT:%.*]] = zext i1 true to i32 +// CHECK-NEXT: [[CMP:%.*]] = icmp ne ptr @b, @a +// CHECK-NEXT: [[ZEXT:%.*]] = zext i1 [[CMP]] to i32 // CHECK-NEXT: [[SITOFP:%.*]] = sitofp i32 [[ZEXT]] to float // CHECK-NEXT: [[LV:%.*]] = load ptr, ptr @c // CHECK-NEXT: store float [[SITOFP]], ptr [[LV]], align 4 diff --git a/clang/test/CodeGenCXX/cxx11-thread-local.cpp b/clang/test/CodeGenCXX/cxx11-thread-local.cpp index 1a6e289c9c2b..bcc490bc32e6 100644 --- a/clang/test/CodeGenCXX/cxx11-thread-local.cpp +++ b/clang/test/CodeGenCXX/cxx11-thread-local.cpp @@ -136,8 +136,9 @@ int f() { // CHECK-NEXT: store i32 %{{.*}}, ptr @c, align 4 // LINUX_AIX-LABEL: define linkonce_odr hidden noundef ptr @_ZTW1b() -// LINUX: br i1 icmp ne (ptr @_ZTH1b, ptr null), -// AIX-NOT: br i1 icmp ne (ptr @_ZTH1b, ptr null), +// LINUX: [[CMP:%.*]] = icmp ne ptr @_ZTH1b, null +// LINUX: br i1 [[CMP]] +// AIX-NOT: [[CMP:%.*]] = icmp ne ptr @_ZTH1b, null // not null: // LINUX_AIX: call void @_ZTH1b() // LINUX: br label @@ -219,24 +220,27 @@ int f() { // DARWIN: declare cxx_fast_tlscc noundef ptr @_ZTWN1VIcE1mE() // LINUX_AIX: define linkonce_odr hidden noundef ptr @_ZTWN1VIcE1mE() {{#[0-9]+}}{{( comdat)?}} { -// LINUX: br i1 icmp ne (ptr @_ZTHN1VIcE1mE, -// AIX-NOT: br i1 icmp ne (ptr @_ZTHN1VIcE1mE +// LINUX: [[CMP:%.*]] = icmp ne ptr @_ZTHN1VIcE1mE, +// LINUX: br i1 [[CMP]] +// AIX-NOT: [[CMP:%.*]] = icmp ne ptr @_ZTHN1VIcE1mE, // LINUX_AIX: call void @_ZTHN1VIcE1mE() // LINUX_AIX: [[VEM_ADDR:%.+]] = call align 4 ptr @llvm.threadlocal.address.p0(ptr align 4 @_ZN1VIcE1mE) // LINUX_AIX: ret ptr [[VEM_ADDR]] // DARWIN: declare cxx_fast_tlscc noundef ptr @_ZTWN1WIcE1mE() // LINUX_AIX: define linkonce_odr hidden noundef ptr @_ZTWN1WIcE1mE() {{#[0-9]+}}{{( comdat)?}} { -// LINUX: br i1 icmp ne (ptr @_ZTHN1WIcE1mE, -// AIX-NOT: br i1 icmp ne (ptr @_ZTHN1WIcE1mE, +// LINUX: [[CMP:%.*]] = icmp ne ptr @_ZTHN1WIcE1mE, +// LINUX: br i1 [[CMP]] +// AIX-NOT: [[CMP:%.*]] = icmp ne ptr @_ZTHN1WIcE1mE, // LINUX_AIX: call void @_ZTHN1WIcE1mE() // LINUX_AIX: [[WEM_ADDR:%.+]] = call align 4 ptr @llvm.threadlocal.address.p0(ptr align 4 @_ZN1WIcE1mE) // LINUX_AIX: ret ptr [[WEM_ADDR]] // DARWIN: declare cxx_fast_tlscc {{.*}}ptr @_ZTWN1XIcE1mE() // LINUX_AIX: define linkonce_odr hidden {{.*}}ptr @_ZTWN1XIcE1mE() {{#[0-9]+}}{{( comdat)?}} { -// LINUX: br i1 icmp ne (ptr @_ZTHN1XIcE1mE, -// AIX-NOT: br i1 icmp ne (ptr @_ZTHN1XIcE1mE, +// LINUX: [[CMP:%.*]] = icmp ne ptr @_ZTHN1XIcE1mE, +// LINUX: br i1 [[CMP]] +// AIX-NOT: [[CMP:%.*]] = icmp ne ptr @_ZTHN1XIcE1mE, // LINUX_AIX: call void @_ZTHN1XIcE1mE() // LINUX_AIX: [[XEM_ADDR:%.+]] = call align 1 ptr @llvm.threadlocal.address.p0(ptr align 1 @_ZN1XIcE1mE) // LINUX_AIX: ret ptr [[XEM_ADDR]] diff --git a/clang/test/CodeGenCXX/ubsan-nullability-arg.cpp b/clang/test/CodeGenCXX/ubsan-nullability-arg.cpp index 4cff87ca32eb..53e324ca9eff 100644 --- a/clang/test/CodeGenCXX/ubsan-nullability-arg.cpp +++ b/clang/test/CodeGenCXX/ubsan-nullability-arg.cpp @@ -10,7 +10,8 @@ struct S0 { void foo1(void (S0::*_Nonnull f)()); // ITANIUM-LABEL: @_ZN10method_ptr5test1Ev(){{.*}} { -// ITANIUM: br i1 icmp ne (i64 ptrtoint (ptr @_ZN10method_ptr2S04foo1Ev to i64), i64 0), label %[[CONT:.*]], label %[[FAIL:[^,]*]] +// ITANIUM: [[CMP:%.*]] = icmp ne i64 ptrtoint (ptr @_ZN10method_ptr2S04foo1Ev to i64), 0 +// ITANIUM: br i1 [[CMP]], label %[[CONT:.*]], label %[[FAIL:[^,]*]] // ITANIUM-EMPTY: // ITANIUM-NEXT: [[FAIL]]: // ITANIUM-NEXT: call void @__ubsan_handle_nullability_arg diff --git a/clang/test/CodeGenCXX/weak-external.cpp b/clang/test/CodeGenCXX/weak-external.cpp index 5eb262cdbead..587fba36a0ad 100644 --- a/clang/test/CodeGenCXX/weak-external.cpp +++ b/clang/test/CodeGenCXX/weak-external.cpp @@ -80,11 +80,13 @@ namespace not_weak_on_first { namespace constant_eval { [[gnu::weak]] extern int a; // CHECK-LABEL: define {{.*}} @__cxx_global_var_init - // CHECK: [[ZEXT:%.*]] = zext i1 icmp ne (ptr @_ZN13constant_eval1aE, ptr null) to i8 + // CHECK: [[CMP:%.*]] = icmp ne ptr @_ZN13constant_eval1aE, null + // CHECK: [[ZEXT:%.*]] = zext i1 [[CMP]] to i8 // CHECK: store i8 [[ZEXT]], ptr @_ZN13constant_eval6has_a1E, bool has_a1 = &a; // CHECK-LABEL: define {{.*}} @__cxx_global_var_init - // CHECK: [[ZEXT:%.*]] = zext i1 icmp ne (ptr @_ZN13constant_eval1aE, ptr null) to i8 + // CHECK: [[CMP:%.*]] = icmp ne ptr @_ZN13constant_eval1aE, null + // CHECK: [[ZEXT:%.*]] = zext i1 [[CMP]] to i8 // CHECK: store i8 [[ZEXT]], ptr @_ZN13constant_eval6has_a2E, bool has_a2 = &a != nullptr; @@ -92,11 +94,16 @@ namespace constant_eval { [[gnu::weak]] void f(); }; // CHECK-LABEL: define {{.*}} @__cxx_global_var_init - // CHECK: [[ZEXT:%.*]] = zext i1 icmp ne (i{{32|64}} ptrtoint (ptr @_ZN13constant_eval1X1fEv to i{{32|64}}), i{{32|64}} 0) to i8 + // CHECK: [[CMP:%.*]] = icmp ne i{{32|64}} ptrtoint (ptr @_ZN13constant_eval1X1fEv to i{{32|64}}), 0 + // CHECK: [[ZEXT:%.*]] = zext i1 [[CMP]] to i8 // CHECK: store i8 [[ZEXT]], ptr @_ZN13constant_eval6has_f1E, bool has_f1 = &X::f; // CHECK-LABEL: define {{.*}} @__cxx_global_var_init - // CHECK: [[ZEXT:%.*]] = zext i1 icmp ne (i{{32|64}} ptrtoint (ptr @_ZN13constant_eval1X1fEv to i{{32|64}}), i{{32|64}} 0) to i8 + // CHECK: [[CMP:%.*]] = icmp ne i{{32|64}} ptrtoint (ptr @_ZN13constant_eval1X1fEv to i{{32|64}}), 0 + // CHECK: [[CMP2:%.*]] = icmp ne i{{32|64}} ptrtoint (ptr @_ZN13constant_eval1X1fEv to i{{32|64}}), 0 + // CHECK: [[AND:%.*]] = and i1 [[CMP2]], false + // CHECK: [[OR:%.*]] = or i1 [[CMP]], [[AND]] + // CHECK: [[ZEXT:%.*]] = zext i1 [[OR]] to i8 // CHECK: store i8 [[ZEXT]], ptr @_ZN13constant_eval6has_f2E, bool has_f2 = &X::f != nullptr; } diff --git a/clang/test/Driver/linker-wrapper-image.c b/clang/test/Driver/linker-wrapper-image.c index 5d5d62805e17..2bc48e6c4d88 100644 --- a/clang/test/Driver/linker-wrapper-image.c +++ b/clang/test/Driver/linker-wrapper-image.c @@ -83,32 +83,33 @@ // CUDA: define internal void @.cuda.globals_reg(ptr %0) section ".text.startup" { // CUDA-NEXT: entry: -// CUDA-NEXT: br i1 icmp ne (ptr @__start_cuda_offloading_entries, ptr @__stop_cuda_offloading_entries), label %while.entry, label %while.end +// CUDA-NEXT: %1 = icmp ne ptr @__start_cuda_offloading_entries, @__stop_cuda_offloading_entries +// CUDA-NEXT: br i1 %1, label %while.entry, label %while.end // CUDA: while.entry: -// CUDA-NEXT: %entry1 = phi ptr [ @__start_cuda_offloading_entries, %entry ], [ %11, %if.end ] -// CUDA-NEXT: %1 = getelementptr inbounds %struct.__tgt_offload_entry, ptr %entry1, i64 0, i32 0 -// CUDA-NEXT: %addr = load ptr, ptr %1, align 8 -// CUDA-NEXT: %2 = getelementptr inbounds %struct.__tgt_offload_entry, ptr %entry1, i64 0, i32 1 -// CUDA-NEXT: %name = load ptr, ptr %2, align 8 -// CUDA-NEXT: %3 = getelementptr inbounds %struct.__tgt_offload_entry, ptr %entry1, i64 0, i32 2 -// CUDA-NEXT: %size = load i64, ptr %3, align 4 -// CUDA-NEXT: %4 = getelementptr inbounds %struct.__tgt_offload_entry, ptr %entry1, i64 0, i32 3 -// CUDA-NEXT: %flags = load i32, ptr %4, align 4 -// CUDA-NEXT: %5 = getelementptr inbounds %struct.__tgt_offload_entry, ptr %entry1, i64 0, i32 4 -// CUDA-NEXT: %textype = load i32, ptr %5, align 4 +// CUDA-NEXT: %entry1 = phi ptr [ @__start_cuda_offloading_entries, %entry ], [ %12, %if.end ] +// CUDA-NEXT: %2 = getelementptr inbounds %struct.__tgt_offload_entry, ptr %entry1, i64 0, i32 0 +// CUDA-NEXT: %addr = load ptr, ptr %2, align 8 +// CUDA-NEXT: %3 = getelementptr inbounds %struct.__tgt_offload_entry, ptr %entry1, i64 0, i32 1 +// CUDA-NEXT: %name = load ptr, ptr %3, align 8 +// CUDA-NEXT: %4 = getelementptr inbounds %struct.__tgt_offload_entry, ptr %entry1, i64 0, i32 2 +// CUDA-NEXT: %size = load i64, ptr %4, align 4 +// CUDA-NEXT: %5 = getelementptr inbounds %struct.__tgt_offload_entry, ptr %entry1, i64 0, i32 3 +// CUDA-NEXT: %flags = load i32, ptr %5, align 4 +// CUDA-NEXT: %6 = getelementptr inbounds %struct.__tgt_offload_entry, ptr %entry1, i64 0, i32 4 +// CUDA-NEXT: %textype = load i32, ptr %6, align 4 // CUDA-NEXT: %type = and i32 %flags, 7 -// CUDA-NEXT: %6 = and i32 %flags, 8 -// CUDA-NEXT: %extern = lshr i32 %6, 3 -// CUDA-NEXT: %7 = and i32 %flags, 16 -// CUDA-NEXT: %constant = lshr i32 %7, 4 -// CUDA-NEXT: %8 = and i32 %flags, 32 -// CUDA-NEXT: %normalized = lshr i32 %8, 5 -// CUDA-NEXT: %9 = icmp eq i64 %size, 0 -// CUDA-NEXT: br i1 %9, label %if.then, label %if.else +// CUDA-NEXT: %7 = and i32 %flags, 8 +// CUDA-NEXT: %extern = lshr i32 %7, 3 +// CUDA-NEXT: %8 = and i32 %flags, 16 +// CUDA-NEXT: %constant = lshr i32 %8, 4 +// CUDA-NEXT: %9 = and i32 %flags, 32 +// CUDA-NEXT: %normalized = lshr i32 %9, 5 +// CUDA-NEXT: %10 = icmp eq i64 %size, 0 +// CUDA-NEXT: br i1 %10, label %if.then, label %if.else // CUDA: if.then: -// CUDA-NEXT: %10 = call i32 @__cudaRegisterFunction(ptr %0, ptr %addr, ptr %name, ptr %name, i32 -1, ptr null, ptr null, ptr null, ptr null, ptr null) +// CUDA-NEXT: %11 = call i32 @__cudaRegisterFunction(ptr %0, ptr %addr, ptr %name, ptr %name, i32 -1, ptr null, ptr null, ptr null, ptr null, ptr null) // CUDA-NEXT: br label %if.end // CUDA: if.else: @@ -133,9 +134,9 @@ // CUDA-NEXT: br label %if.end // CUDA: if.end: -// CUDA-NEXT: %11 = getelementptr inbounds %struct.__tgt_offload_entry, ptr %entry1, i64 1 -// CUDA-NEXT: %12 = icmp eq ptr %11, @__stop_cuda_offloading_entries -// CUDA-NEXT: br i1 %12, label %while.end, label %while.entry +// CUDA-NEXT: %12 = getelementptr inbounds %struct.__tgt_offload_entry, ptr %entry1, i64 1 +// CUDA-NEXT: %13 = icmp eq ptr %12, @__stop_cuda_offloading_entries +// CUDA-NEXT: br i1 %13, label %while.end, label %while.entry // CUDA: while.end: // CUDA-NEXT: ret void @@ -182,32 +183,33 @@ // HIP: define internal void @.hip.globals_reg(ptr %0) section ".text.startup" { // HIP-NEXT: entry: -// HIP-NEXT: br i1 icmp ne (ptr @__start_hip_offloading_entries, ptr @__stop_hip_offloading_entries), label %while.entry, label %while.end +// HIP-NEXT: %1 = icmp ne ptr @__start_hip_offloading_entries, @__stop_hip_offloading_entries +// HIP-NEXT: br i1 %1, label %while.entry, label %while.end // HIP: while.entry: -// HIP-NEXT: %entry1 = phi ptr [ @__start_hip_offloading_entries, %entry ], [ %11, %if.end ] -// HIP-NEXT: %1 = getelementptr inbounds %struct.__tgt_offload_entry, ptr %entry1, i64 0, i32 0 -// HIP-NEXT: %addr = load ptr, ptr %1, align 8 -// HIP-NEXT: %2 = getelementptr inbounds %struct.__tgt_offload_entry, ptr %entry1, i64 0, i32 1 -// HIP-NEXT: %name = load ptr, ptr %2, align 8 -// HIP-NEXT: %3 = getelementptr inbounds %struct.__tgt_offload_entry, ptr %entry1, i64 0, i32 2 -// HIP-NEXT: %size = load i64, ptr %3, align 4 -// HIP-NEXT: %4 = getelementptr inbounds %struct.__tgt_offload_entry, ptr %entry1, i64 0, i32 3 -// HIP-NEXT: %flags = load i32, ptr %4, align 4 -// HIP-NEXT: %5 = getelementptr inbounds %struct.__tgt_offload_entry, ptr %entry1, i64 0, i32 4 -// HIP-NEXT: %textype = load i32, ptr %5, align 4 +// HIP-NEXT: %entry1 = phi ptr [ @__start_hip_offloading_entries, %entry ], [ %12, %if.end ] +// HIP-NEXT: %2 = getelementptr inbounds %struct.__tgt_offload_entry, ptr %entry1, i64 0, i32 0 +// HIP-NEXT: %addr = load ptr, ptr %2, align 8 +// HIP-NEXT: %3 = getelementptr inbounds %struct.__tgt_offload_entry, ptr %entry1, i64 0, i32 1 +// HIP-NEXT: %name = load ptr, ptr %3, align 8 +// HIP-NEXT: %4 = getelementptr inbounds %struct.__tgt_offload_entry, ptr %entry1, i64 0, i32 2 +// HIP-NEXT: %size = load i64, ptr %4, align 4 +// HIP-NEXT: %5 = getelementptr inbounds %struct.__tgt_offload_entry, ptr %entry1, i64 0, i32 3 +// HIP-NEXT: %flags = load i32, ptr %5, align 4 +// HIP-NEXT: %6 = getelementptr inbounds %struct.__tgt_offload_entry, ptr %entry1, i64 0, i32 4 +// HIP-NEXT: %textype = load i32, ptr %6, align 4 // HIP-NEXT: %type = and i32 %flags, 7 -// HIP-NEXT: %6 = and i32 %flags, 8 -// HIP-NEXT: %extern = lshr i32 %6, 3 -// HIP-NEXT: %7 = and i32 %flags, 16 -// HIP-NEXT: %constant = lshr i32 %7, 4 -// HIP-NEXT: %8 = and i32 %flags, 32 -// HIP-NEXT: %normalized = lshr i32 %8, 5 -// HIP-NEXT: %9 = icmp eq i64 %size, 0 -// HIP-NEXT: br i1 %9, label %if.then, label %if.else +// HIP-NEXT: %7 = and i32 %flags, 8 +// HIP-NEXT: %extern = lshr i32 %7, 3 +// HIP-NEXT: %8 = and i32 %flags, 16 +// HIP-NEXT: %constant = lshr i32 %8, 4 +// HIP-NEXT: %9 = and i32 %flags, 32 +// HIP-NEXT: %normalized = lshr i32 %9, 5 +// HIP-NEXT: %10 = icmp eq i64 %size, 0 +// HIP-NEXT: br i1 %10, label %if.then, label %if.else // HIP: if.then: -// HIP-NEXT: %10 = call i32 @__hipRegisterFunction(ptr %0, ptr %addr, ptr %name, ptr %name, i32 -1, ptr null, ptr null, ptr null, ptr null, ptr null) +// HIP-NEXT: %11 = call i32 @__hipRegisterFunction(ptr %0, ptr %addr, ptr %name, ptr %name, i32 -1, ptr null, ptr null, ptr null, ptr null, ptr null) // HIP-NEXT: br label %if.end // HIP: if.else: @@ -234,9 +236,9 @@ // HIP-NEXT: br label %if.end // HIP: if.end: -// HIP-NEXT: %11 = getelementptr inbounds %struct.__tgt_offload_entry, ptr %entry1, i64 1 -// HIP-NEXT: %12 = icmp eq ptr %11, @__stop_hip_offloading_entries -// HIP-NEXT: br i1 %12, label %while.end, label %while.entry +// HIP-NEXT: %12 = getelementptr inbounds %struct.__tgt_offload_entry, ptr %entry1, i64 1 +// HIP-NEXT: %13 = icmp eq ptr %12, @__stop_hip_offloading_entries +// HIP-NEXT: br i1 %13, label %while.end, label %while.entry // HIP: while.end: // HIP-NEXT: ret void diff --git a/clang/test/OpenMP/threadprivate_codegen.cpp b/clang/test/OpenMP/threadprivate_codegen.cpp index b27783be829d..5087451b944b 100644 --- a/clang/test/OpenMP/threadprivate_codegen.cpp +++ b/clang/test/OpenMP/threadprivate_codegen.cpp @@ -3648,24 +3648,26 @@ int foobar() { // // CHECK-TLS1-LABEL: define {{[^@]+}}@_ZTWN6Static1sE // CHECK-TLS1-SAME: () #[[ATTR5]] comdat { -// CHECK-TLS1-NEXT: br i1 icmp ne (ptr @_ZTHN6Static1sE, ptr null), label [[TMP1:%.*]], label [[TMP2:%.*]] -// CHECK-TLS1: 1: -// CHECK-TLS1-NEXT: call void @_ZTHN6Static1sE() -// CHECK-TLS1-NEXT: br label [[TMP2]] +// CHECK-TLS1-NEXT: [[TMP1:%.*]] = icmp ne ptr @_ZTHN6Static1sE, null +// CHECK-TLS1-NEXT: br i1 [[TMP1]], label [[TMP2:%.*]], label [[TMP3:%.*]] // CHECK-TLS1: 2: -// CHECK-TLS1-NEXT: [[TMP3:%.*]] = call align 4 ptr @llvm.threadlocal.address.p0(ptr align 4 @_ZN6Static1sE) -// CHECK-TLS1-NEXT: ret ptr [[TMP3]] +// CHECK-TLS1-NEXT: call void @_ZTHN6Static1sE() +// CHECK-TLS1-NEXT: br label [[TMP3]] +// CHECK-TLS1: 3: +// CHECK-TLS1-NEXT: [[TMP4:%.*]] = call align 4 ptr @llvm.threadlocal.address.p0(ptr align 4 @_ZN6Static1sE) +// CHECK-TLS1-NEXT: ret ptr [[TMP4]] // // // CHECK-TLS1-LABEL: define {{[^@]+}}@_ZTW3gs3 // CHECK-TLS1-SAME: () #[[ATTR5]] comdat { -// CHECK-TLS1-NEXT: br i1 icmp ne (ptr @_ZTH3gs3, ptr null), label [[TMP1:%.*]], label [[TMP2:%.*]] -// CHECK-TLS1: 1: -// CHECK-TLS1-NEXT: call void @_ZTH3gs3() -// CHECK-TLS1-NEXT: br label [[TMP2]] +// CHECK-TLS1-NEXT: [[TMP1:%.*]] = icmp ne ptr @_ZTH3gs3, null +// CHECK-TLS1-NEXT: br i1 [[TMP1]], label [[TMP2:%.*]], label [[TMP3:%.*]] // CHECK-TLS1: 2: -// CHECK-TLS1-NEXT: [[TMP3:%.*]] = call align 4 ptr @llvm.threadlocal.address.p0(ptr align 4 @gs3) -// CHECK-TLS1-NEXT: ret ptr [[TMP3]] +// CHECK-TLS1-NEXT: call void @_ZTH3gs3() +// CHECK-TLS1-NEXT: br label [[TMP3]] +// CHECK-TLS1: 3: +// CHECK-TLS1-NEXT: [[TMP4:%.*]] = call align 4 ptr @llvm.threadlocal.address.p0(ptr align 4 @gs3) +// CHECK-TLS1-NEXT: ret ptr [[TMP4]] // // // CHECK-TLS1-LABEL: define {{[^@]+}}@_ZTW5arr_x @@ -3950,24 +3952,26 @@ int foobar() { // // CHECK-TLS2-LABEL: define {{[^@]+}}@_ZTWN6Static1sE // CHECK-TLS2-SAME: () #[[ATTR1]] comdat { -// CHECK-TLS2-NEXT: br i1 icmp ne (ptr @_ZTHN6Static1sE, ptr null), label [[TMP1:%.*]], label [[TMP2:%.*]] -// CHECK-TLS2: 1: -// CHECK-TLS2-NEXT: call void @_ZTHN6Static1sE() -// CHECK-TLS2-NEXT: br label [[TMP2]] +// CHECK-TLS2-NEXT: [[TMP1:%.*]] = icmp ne ptr @_ZTHN6Static1sE, null +// CHECK-TLS2-NEXT: br i1 [[TMP1]], label [[TMP2:%.*]], label [[TMP3:%.*]] // CHECK-TLS2: 2: -// CHECK-TLS2-NEXT: [[TMP3:%.*]] = call align 4 ptr @llvm.threadlocal.address.p0(ptr align 4 @_ZN6Static1sE) -// CHECK-TLS2-NEXT: ret ptr [[TMP3]] +// CHECK-TLS2-NEXT: call void @_ZTHN6Static1sE() +// CHECK-TLS2-NEXT: br label [[TMP3]] +// CHECK-TLS2: 3: +// CHECK-TLS2-NEXT: [[TMP4:%.*]] = call align 4 ptr @llvm.threadlocal.address.p0(ptr align 4 @_ZN6Static1sE) +// CHECK-TLS2-NEXT: ret ptr [[TMP4]] // // // CHECK-TLS2-LABEL: define {{[^@]+}}@_ZTW3gs3 // CHECK-TLS2-SAME: () #[[ATTR1]] comdat { -// CHECK-TLS2-NEXT: br i1 icmp ne (ptr @_ZTH3gs3, ptr null), label [[TMP1:%.*]], label [[TMP2:%.*]] -// CHECK-TLS2: 1: -// CHECK-TLS2-NEXT: call void @_ZTH3gs3() -// CHECK-TLS2-NEXT: br label [[TMP2]] +// CHECK-TLS2-NEXT: [[TMP1:%.*]] = icmp ne ptr @_ZTH3gs3, null +// CHECK-TLS2-NEXT: br i1 [[TMP1]], label [[TMP2:%.*]], label [[TMP3:%.*]] // CHECK-TLS2: 2: -// CHECK-TLS2-NEXT: [[TMP3:%.*]] = call align 4 ptr @llvm.threadlocal.address.p0(ptr align 4 @gs3) -// CHECK-TLS2-NEXT: ret ptr [[TMP3]] +// CHECK-TLS2-NEXT: call void @_ZTH3gs3() +// CHECK-TLS2-NEXT: br label [[TMP3]] +// CHECK-TLS2: 3: +// CHECK-TLS2-NEXT: [[TMP4:%.*]] = call align 4 ptr @llvm.threadlocal.address.p0(ptr align 4 @gs3) +// CHECK-TLS2-NEXT: ret ptr [[TMP4]] // // // CHECK-TLS2-LABEL: define {{[^@]+}}@_ZTW5arr_x @@ -4723,24 +4727,26 @@ int foobar() { // // CHECK-TLS3-LABEL: define {{[^@]+}}@_ZTWN6Static1sE // CHECK-TLS3-SAME: () #[[ATTR6]] comdat { -// CHECK-TLS3-NEXT: br i1 icmp ne (ptr @_ZTHN6Static1sE, ptr null), label [[TMP1:%.*]], label [[TMP2:%.*]] -// CHECK-TLS3: 1: -// CHECK-TLS3-NEXT: call void @_ZTHN6Static1sE() -// CHECK-TLS3-NEXT: br label [[TMP2]] +// CHECK-TLS3-NEXT: [[TMP1:%.*]] = icmp ne ptr @_ZTHN6Static1sE, null +// CHECK-TLS3-NEXT: br i1 [[TMP1]], label [[TMP2:%.*]], label [[TMP3:%.*]] // CHECK-TLS3: 2: -// CHECK-TLS3-NEXT: [[TMP3:%.*]] = call align 4 ptr @llvm.threadlocal.address.p0(ptr align 4 @_ZN6Static1sE) -// CHECK-TLS3-NEXT: ret ptr [[TMP3]] +// CHECK-TLS3-NEXT: call void @_ZTHN6Static1sE() +// CHECK-TLS3-NEXT: br label [[TMP3]] +// CHECK-TLS3: 3: +// CHECK-TLS3-NEXT: [[TMP4:%.*]] = call align 4 ptr @llvm.threadlocal.address.p0(ptr align 4 @_ZN6Static1sE) +// CHECK-TLS3-NEXT: ret ptr [[TMP4]] // // // CHECK-TLS3-LABEL: define {{[^@]+}}@_ZTW3gs3 // CHECK-TLS3-SAME: () #[[ATTR6]] comdat { -// CHECK-TLS3-NEXT: br i1 icmp ne (ptr @_ZTH3gs3, ptr null), label [[TMP1:%.*]], label [[TMP2:%.*]] -// CHECK-TLS3: 1: -// CHECK-TLS3-NEXT: call void @_ZTH3gs3() -// CHECK-TLS3-NEXT: br label [[TMP2]] +// CHECK-TLS3-NEXT: [[TMP1:%.*]] = icmp ne ptr @_ZTH3gs3, null +// CHECK-TLS3-NEXT: br i1 [[TMP1]], label [[TMP2:%.*]], label [[TMP3:%.*]] // CHECK-TLS3: 2: -// CHECK-TLS3-NEXT: [[TMP3:%.*]] = call align 4 ptr @llvm.threadlocal.address.p0(ptr align 4 @gs3) -// CHECK-TLS3-NEXT: ret ptr [[TMP3]] +// CHECK-TLS3-NEXT: call void @_ZTH3gs3() +// CHECK-TLS3-NEXT: br label [[TMP3]] +// CHECK-TLS3: 3: +// CHECK-TLS3-NEXT: [[TMP4:%.*]] = call align 4 ptr @llvm.threadlocal.address.p0(ptr align 4 @gs3) +// CHECK-TLS3-NEXT: ret ptr [[TMP4]] // // // CHECK-TLS3-LABEL: define {{[^@]+}}@_ZTW5arr_x @@ -5039,24 +5045,26 @@ int foobar() { // // CHECK-TLS4-LABEL: define {{[^@]+}}@_ZTWN6Static1sE // CHECK-TLS4-SAME: () #[[ATTR2]] comdat { -// CHECK-TLS4-NEXT: br i1 icmp ne (ptr @_ZTHN6Static1sE, ptr null), label [[TMP1:%.*]], label [[TMP2:%.*]] -// CHECK-TLS4: 1: -// CHECK-TLS4-NEXT: call void @_ZTHN6Static1sE() -// CHECK-TLS4-NEXT: br label [[TMP2]] +// CHECK-TLS4-NEXT: [[TMP1:%.*]] = icmp ne ptr @_ZTHN6Static1sE, null +// CHECK-TLS4-NEXT: br i1 [[TMP1]], label [[TMP2:%.*]], label [[TMP3:%.*]] // CHECK-TLS4: 2: -// CHECK-TLS4-NEXT: [[TMP3:%.*]] = call align 4 ptr @llvm.threadlocal.address.p0(ptr align 4 @_ZN6Static1sE) -// CHECK-TLS4-NEXT: ret ptr [[TMP3]] +// CHECK-TLS4-NEXT: call void @_ZTHN6Static1sE() +// CHECK-TLS4-NEXT: br label [[TMP3]] +// CHECK-TLS4: 3: +// CHECK-TLS4-NEXT: [[TMP4:%.*]] = call align 4 ptr @llvm.threadlocal.address.p0(ptr align 4 @_ZN6Static1sE) +// CHECK-TLS4-NEXT: ret ptr [[TMP4]] // // // CHECK-TLS4-LABEL: define {{[^@]+}}@_ZTW3gs3 // CHECK-TLS4-SAME: () #[[ATTR2]] comdat { -// CHECK-TLS4-NEXT: br i1 icmp ne (ptr @_ZTH3gs3, ptr null), label [[TMP1:%.*]], label [[TMP2:%.*]] -// CHECK-TLS4: 1: -// CHECK-TLS4-NEXT: call void @_ZTH3gs3() -// CHECK-TLS4-NEXT: br label [[TMP2]] +// CHECK-TLS4-NEXT: [[TMP1:%.*]] = icmp ne ptr @_ZTH3gs3, null +// CHECK-TLS4-NEXT: br i1 [[TMP1]], label [[TMP2:%.*]], label [[TMP3:%.*]] // CHECK-TLS4: 2: -// CHECK-TLS4-NEXT: [[TMP3:%.*]] = call align 4 ptr @llvm.threadlocal.address.p0(ptr align 4 @gs3) -// CHECK-TLS4-NEXT: ret ptr [[TMP3]] +// CHECK-TLS4-NEXT: call void @_ZTH3gs3() +// CHECK-TLS4-NEXT: br label [[TMP3]] +// CHECK-TLS4: 3: +// CHECK-TLS4-NEXT: [[TMP4:%.*]] = call align 4 ptr @llvm.threadlocal.address.p0(ptr align 4 @gs3) +// CHECK-TLS4-NEXT: ret ptr [[TMP4]] // // // CHECK-TLS4-LABEL: define {{[^@]+}}@_ZTW5arr_x diff --git a/llvm/include/llvm/Analysis/TargetFolder.h b/llvm/include/llvm/Analysis/TargetFolder.h index f95d738a4065..26ec4dcef6df 100644 --- a/llvm/include/llvm/Analysis/TargetFolder.h +++ b/llvm/include/llvm/Analysis/TargetFolder.h @@ -103,7 +103,7 @@ public: auto *LC = dyn_cast(LHS); auto *RC = dyn_cast(RHS); if (LC && RC) - return Fold(ConstantExpr::getCompare(P, LC, RC)); + return ConstantFoldCompareInstOperands(P, LC, RC, DL); return nullptr; } diff --git a/llvm/include/llvm/IR/ConstantFolder.h b/llvm/include/llvm/IR/ConstantFolder.h index ce4b44ddc855..65467bdbb303 100644 --- a/llvm/include/llvm/IR/ConstantFolder.h +++ b/llvm/include/llvm/IR/ConstantFolder.h @@ -99,7 +99,7 @@ public: auto *LC = dyn_cast(LHS); auto *RC = dyn_cast(RHS); if (LC && RC) - return ConstantExpr::getCompare(P, LC, RC); + return ConstantFoldCompareInstruction(P, LC, RC); return nullptr; } diff --git a/llvm/lib/Analysis/ConstantFolding.cpp b/llvm/lib/Analysis/ConstantFolding.cpp index 31667ff3951f..c73558799556 100644 --- a/llvm/lib/Analysis/ConstantFolding.cpp +++ b/llvm/lib/Analysis/ConstantFolding.cpp @@ -1268,7 +1268,7 @@ Constant *llvm::ConstantFoldCompareInstOperands( if (!Ops1) return nullptr; - return ConstantExpr::getCompare(Predicate, Ops0, Ops1); + return ConstantFoldCompareInstruction(Predicate, Ops0, Ops1); } Constant *llvm::ConstantFoldUnaryOpOperand(unsigned Opcode, Constant *Op, diff --git a/llvm/lib/IR/ConstantFold.cpp b/llvm/lib/IR/ConstantFold.cpp index 4622ad7e9a0e..2c99f39a0249 100644 --- a/llvm/lib/IR/ConstantFold.cpp +++ b/llvm/lib/IR/ConstantFold.cpp @@ -1282,9 +1282,9 @@ Constant *llvm::ConstantFoldCompareInstruction(CmpInst::Predicate Predicate, // Fast path for splatted constants. if (Constant *C1Splat = C1->getSplatValue()) if (Constant *C2Splat = C2->getSplatValue()) - return ConstantVector::getSplat( - C1VTy->getElementCount(), - ConstantExpr::getCompare(Predicate, C1Splat, C2Splat)); + if (Constant *Elt = + ConstantFoldCompareInstruction(Predicate, C1Splat, C2Splat)) + return ConstantVector::getSplat(C1VTy->getElementCount(), Elt); // Do not iterate on scalable vector. The number of elements is unknown at // compile-time. @@ -1302,8 +1302,11 @@ Constant *llvm::ConstantFoldCompareInstruction(CmpInst::Predicate Predicate, ConstantExpr::getExtractElement(C1, ConstantInt::get(Ty, I)); Constant *C2E = ConstantExpr::getExtractElement(C2, ConstantInt::get(Ty, I)); + Constant *Elt = ConstantFoldCompareInstruction(Predicate, C1E, C2E); + if (!Elt) + return nullptr; - ResElts.push_back(ConstantExpr::getCompare(Predicate, C1E, C2E)); + ResElts.push_back(Elt); } return ConstantVector::get(ResElts); @@ -1411,7 +1414,7 @@ Constant *llvm::ConstantFoldCompareInstruction(CmpInst::Predicate Predicate, // other way if possible. // Also, if C1 is null and C2 isn't, flip them around. Predicate = ICmpInst::getSwappedPredicate(Predicate); - return ConstantExpr::getICmp(Predicate, C2, C1); + return ConstantFoldCompareInstruction(Predicate, C2, C1); } } return nullptr; diff --git a/llvm/test/Assembler/ConstantExprFold.ll b/llvm/test/Assembler/ConstantExprFold.ll index ab7e767d767b..fb40f82c861b 100644 --- a/llvm/test/Assembler/ConstantExprFold.ll +++ b/llvm/test/Assembler/ConstantExprFold.ll @@ -43,9 +43,9 @@ ; CHECK: @mul = global ptr null ; CHECK: @xor = global ptr @A ; CHECK: @B = external global %Ty -; CHECK: @icmp_ult1 = global i1 icmp ugt (ptr getelementptr inbounds (i64, ptr @A, i64 1), ptr @A) +; CHECK: @icmp_ult1 = global i1 icmp ult (ptr @A, ptr getelementptr inbounds (i64, ptr @A, i64 1)) ; CHECK: @icmp_slt = global i1 false -; CHECK: @icmp_ult2 = global i1 icmp ugt (ptr getelementptr inbounds (%Ty, ptr @B, i64 0, i32 1), ptr @B) +; CHECK: @icmp_ult2 = global i1 icmp ult (ptr @B, ptr getelementptr inbounds (%Ty, ptr @B, i64 0, i32 1)) ; CHECK: @cons = weak global i32 0, align 8 ; CHECK: @gep1 = global <2 x ptr> undef ; CHECK: @gep2 = global <2 x ptr> undef diff --git a/llvm/test/Assembler/ConstantExprNoFold.ll b/llvm/test/Assembler/ConstantExprNoFold.ll index 4f08463d88d1..a676a0c7eb36 100644 --- a/llvm/test/Assembler/ConstantExprNoFold.ll +++ b/llvm/test/Assembler/ConstantExprNoFold.ll @@ -51,9 +51,9 @@ target datalayout = "p:32:32" @addrspace3 = internal addrspace(3) global i32 undef ; CHECK: @no.fold.addrspace.icmp.eq.gv.null = global i1 icmp eq (ptr addrspace(3) @addrspace3, ptr addrspace(3) null) -; CHECK: @no.fold.addrspace.icmp.eq.null.gv = global i1 icmp eq (ptr addrspace(3) @addrspace3, ptr addrspace(3) null) +; CHECK: @no.fold.addrspace.icmp.eq.null.gv = global i1 icmp eq (ptr addrspace(3) null, ptr addrspace(3) @addrspace3) ; CHECK: @no.fold.addrspace.icmp.ne.gv.null = global i1 icmp ne (ptr addrspace(3) @addrspace3, ptr addrspace(3) null) -; CHECK: @no.fold.addrspace.icmp.ne.null.gv = global i1 icmp ne (ptr addrspace(3) @addrspace3, ptr addrspace(3) null) +; CHECK: @no.fold.addrspace.icmp.ne.null.gv = global i1 icmp ne (ptr addrspace(3) null, ptr addrspace(3) @addrspace3) @no.fold.addrspace.icmp.eq.gv.null = global i1 icmp eq (ptr addrspace(3) @addrspace3, ptr addrspace(3) null) @no.fold.addrspace.icmp.eq.null.gv = global i1 icmp eq (ptr addrspace(3) null, ptr addrspace(3) @addrspace3) @no.fold.addrspace.icmp.ne.gv.null = global i1 icmp ne (ptr addrspace(3) @addrspace3, ptr addrspace(3) null) diff --git a/llvm/test/Assembler/vector-cmp.ll b/llvm/test/Assembler/vector-cmp.ll index 23fe54f84595..a90046bc2426 100644 --- a/llvm/test/Assembler/vector-cmp.ll +++ b/llvm/test/Assembler/vector-cmp.ll @@ -4,7 +4,7 @@ target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:128:128" target triple = "i686-apple-darwin9.2.2" -; CHECK: @1 = global <4 x i1> +; CHECK: @1 = global <4 x i1> icmp slt (<4 x i32> , <4 x i32> ) define <4 x i1> @foo(<4 x float> %a, <4 x float> %b) nounwind { entry: diff --git a/llvm/test/CodeGen/AMDGPU/lower-ctor-dtor-constexpr-alias.ll b/llvm/test/CodeGen/AMDGPU/lower-ctor-dtor-constexpr-alias.ll index 95fc47469b51..2ad40ef5e547 100644 --- a/llvm/test/CodeGen/AMDGPU/lower-ctor-dtor-constexpr-alias.ll +++ b/llvm/test/CodeGen/AMDGPU/lower-ctor-dtor-constexpr-alias.ll @@ -48,7 +48,8 @@ define void @bar() addrspace(1) { ; CHECK-LABEL: define weak_odr amdgpu_kernel void @amdgcn.device.init( ; CHECK-SAME: ) #[[ATTR1:[0-9]+]] { ; CHECK-NEXT: entry: -; CHECK-NEXT: br i1 icmp ne (ptr addrspace(1) @__init_array_start, ptr addrspace(1) @__init_array_end), label [[WHILE_ENTRY:%.*]], label [[WHILE_END:%.*]] +; CHECK-NEXT: [[TMP0:%.*]] = icmp ne ptr addrspace(1) @__init_array_start, @__init_array_end +; CHECK-NEXT: br i1 [[TMP0]], label [[WHILE_ENTRY:%.*]], label [[WHILE_END:%.*]] ; CHECK: while.entry: ; CHECK-NEXT: [[PTR:%.*]] = phi ptr addrspace(1) [ @__init_array_start, [[ENTRY:%.*]] ], [ [[NEXT:%.*]], [[WHILE_ENTRY]] ] ; CHECK-NEXT: [[CALLBACK:%.*]] = load ptr, ptr addrspace(1) [[PTR]], align 8 diff --git a/llvm/test/CodeGen/AMDGPU/lower-ctor-dtor.ll b/llvm/test/CodeGen/AMDGPU/lower-ctor-dtor.ll index c4f0821caacd..503f3b1d896f 100644 --- a/llvm/test/CodeGen/AMDGPU/lower-ctor-dtor.ll +++ b/llvm/test/CodeGen/AMDGPU/lower-ctor-dtor.ll @@ -63,7 +63,8 @@ define internal void @bar() { ; CHECK-LABEL: define weak_odr amdgpu_kernel void @amdgcn.device.init( ; CHECK-SAME: ) #[[ATTR0:[0-9]+]] { ; CHECK-NEXT: entry: -; CHECK-NEXT: br i1 icmp ne (ptr addrspace(1) @__init_array_start, ptr addrspace(1) @__init_array_end), label [[WHILE_ENTRY:%.*]], label [[WHILE_END:%.*]] +; CHECK-NEXT: [[TMP0:%.*]] = icmp ne ptr addrspace(1) @__init_array_start, @__init_array_end +; CHECK-NEXT: br i1 [[TMP0]], label [[WHILE_ENTRY:%.*]], label [[WHILE_END:%.*]] ; CHECK: while.entry: ; CHECK-NEXT: [[PTR:%.*]] = phi ptr addrspace(1) [ @__init_array_start, [[ENTRY:%.*]] ], [ [[NEXT:%.*]], [[WHILE_ENTRY]] ] ; CHECK-NEXT: [[CALLBACK:%.*]] = load ptr, ptr addrspace(1) [[PTR]], align 8 diff --git a/llvm/test/CodeGen/AMDGPU/lower-multiple-ctor-dtor.ll b/llvm/test/CodeGen/AMDGPU/lower-multiple-ctor-dtor.ll index f2d73b24c35d..9d00b676d661 100644 --- a/llvm/test/CodeGen/AMDGPU/lower-multiple-ctor-dtor.ll +++ b/llvm/test/CodeGen/AMDGPU/lower-multiple-ctor-dtor.ll @@ -55,7 +55,8 @@ define internal void @bar.5() { ; CHECK-LABEL: define weak_odr amdgpu_kernel void @amdgcn.device.init( ; CHECK-SAME: ) #[[ATTR0:[0-9]+]] { ; CHECK-NEXT: entry: -; CHECK-NEXT: br i1 icmp ne (ptr addrspace(1) @__init_array_start, ptr addrspace(1) @__init_array_end), label [[WHILE_ENTRY:%.*]], label [[WHILE_END:%.*]] +; CHECK-NEXT: [[TMP0:%.*]] = icmp ne ptr addrspace(1) @__init_array_start, @__init_array_end +; CHECK-NEXT: br i1 [[TMP0]], label [[WHILE_ENTRY:%.*]], label [[WHILE_END:%.*]] ; CHECK: while.entry: ; CHECK-NEXT: [[PTR:%.*]] = phi ptr addrspace(1) [ @__init_array_start, [[ENTRY:%.*]] ], [ [[NEXT:%.*]], [[WHILE_ENTRY]] ] ; CHECK-NEXT: [[CALLBACK:%.*]] = load ptr, ptr addrspace(1) [[PTR]], align 8 diff --git a/llvm/test/Instrumentation/MemorySanitizer/check-constant-shadow.ll b/llvm/test/Instrumentation/MemorySanitizer/check-constant-shadow.ll index 2e89bbd2dcff..df032b385054 100644 --- a/llvm/test/Instrumentation/MemorySanitizer/check-constant-shadow.ll +++ b/llvm/test/Instrumentation/MemorySanitizer/check-constant-shadow.ll @@ -73,7 +73,8 @@ entry: } ; CHECK-LABEL: @MaybeUninitializedRetNoUndef -; CONST: br i1 icmp ne (i32 extractelement (<4 x i32> bitcast (<2 x i64> to <4 x i32>), i64 0), i32 0) +; CONST: [[CMP:%.*]] = icmp ne i32 extractelement (<4 x i32> bitcast (<2 x i64> to <4 x i32>), i64 0), 0 +; CONST: br i1 [[CMP]] ; CONST: call void @__msan_warning_with_origin_noreturn ; CHECK: call void @__msan_init() diff --git a/llvm/test/Instrumentation/SanitizerBinaryMetadata/atomics.ll b/llvm/test/Instrumentation/SanitizerBinaryMetadata/atomics.ll index 7d4086c49503..82b65fe33cd6 100644 --- a/llvm/test/Instrumentation/SanitizerBinaryMetadata/atomics.ll +++ b/llvm/test/Instrumentation/SanitizerBinaryMetadata/atomics.ll @@ -2037,7 +2037,8 @@ entry: ; CHECK-LABEL: __sanitizer_metadata_atomics.module_ctor ; CHECK-DAG: entry: -; CHECK-NEXT: br i1 icmp ne (ptr @__sanitizer_metadata_atomics_add, ptr null), label %callfunc, label %ret +; CHECK-NEXT: [[CMP:%.*]] = icmp ne ptr @__sanitizer_metadata_atomics_add, null +; CHECK-NEXT: br i1 [[CMP]], label %callfunc, label %ret ; CHECK-DAG: callfunc: ; CHECK-NEXT: call void @__sanitizer_metadata_atomics_add(i32 2, ptr @__start_sanmd_atomics, ptr @__stop_sanmd_atomics) ; CHECK-NEXT: br label %ret @@ -2046,7 +2047,8 @@ entry: ; CHECK-LABEL: __sanitizer_metadata_atomics.module_dtor ; CHECK-DAG: entry: -; CHECK-NEXT: br i1 icmp ne (ptr @__sanitizer_metadata_atomics_del, ptr null), label %callfunc, label %ret +; CHECK-NEXT: [[CMP:%.*]] = icmp ne ptr @__sanitizer_metadata_atomics_del, null +; CHECK-NEXT: br i1 [[CMP]], label %callfunc, label %ret ; CHECK-DAG: callfunc: ; CHECK-NEXT: call void @__sanitizer_metadata_atomics_del(i32 2, ptr @__start_sanmd_atomics, ptr @__stop_sanmd_atomics) ; CHECK-NEXT: br label %ret @@ -2055,7 +2057,8 @@ entry: ; CHECK-LABEL: __sanitizer_metadata_covered.module_ctor ; CHECK-DAG: entry: -; CHECK-NEXT: br i1 icmp ne (ptr @__sanitizer_metadata_covered_add, ptr null), label %callfunc, label %ret +; CHECK-NEXT: [[CMP:%.*]] = icmp ne ptr @__sanitizer_metadata_covered_add, null +; CHECK-NEXT: br i1 [[CMP]], label %callfunc, label %ret ; CHECK-DAG: callfunc: ; CHECK-NEXT: call void @__sanitizer_metadata_covered_add(i32 2, ptr @__start_sanmd_covered, ptr @__stop_sanmd_covered) ; CHECK-NEXT: br label %ret @@ -2064,7 +2067,8 @@ entry: ; CHECK-LABEL: __sanitizer_metadata_covered.module_dtor ; CHECK-DAG: entry: -; CHECK-NEXT: br i1 icmp ne (ptr @__sanitizer_metadata_covered_del, ptr null), label %callfunc, label %ret +; CHECK-NEXT: [[CMP:%.*]] = icmp ne ptr @__sanitizer_metadata_covered_del, null +; CHECK-NEXT: br i1 [[CMP]], label %callfunc, label %ret ; CHECK-DAG: callfunc: ; CHECK-NEXT: call void @__sanitizer_metadata_covered_del(i32 2, ptr @__start_sanmd_covered, ptr @__stop_sanmd_covered) ; CHECK-NEXT: br label %ret diff --git a/llvm/test/Transforms/Attributor/value-simplify.ll b/llvm/test/Transforms/Attributor/value-simplify.ll index 62d4f63677df..53edd566c542 100644 --- a/llvm/test/Transforms/Attributor/value-simplify.ll +++ b/llvm/test/Transforms/Attributor/value-simplify.ll @@ -1396,11 +1396,6 @@ define internal void @not_called2() { ret void } define internal void @not_called3() { -; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) -; TUNIT-LABEL: define {{[^@]+}}@not_called3 -; TUNIT-SAME: () #[[ATTR2]] { -; TUNIT-NEXT: ret void -; ; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) ; CGSCC-LABEL: define {{[^@]+}}@not_called3 ; CGSCC-SAME: () #[[ATTR1]] { @@ -1422,7 +1417,7 @@ define i1 @user_of_not_called() { ; CHECK-LABEL: define {{[^@]+}}@user_of_not_called() { ; CHECK-NEXT: call void @useFnDecl(ptr addrspace(42) noundef nonnull addrspacecast (ptr @not_called1 to ptr addrspace(42))) ; CHECK-NEXT: call void @useFnDef(ptr addrspace(42) noundef nonnull addrspacecast (ptr @not_called2 to ptr addrspace(42))) -; CHECK-NEXT: ret i1 icmp eq (ptr addrspace(42) addrspacecast (ptr @not_called3 to ptr addrspace(42)), ptr addrspace(42) null) +; CHECK-NEXT: ret i1 false ; call void @useFnDecl(ptr addrspace(42) addrspacecast (ptr @not_called1 to ptr addrspace(42))) call void @useFnDef(ptr addrspace(42) addrspacecast (ptr @not_called2 to ptr addrspace(42))) diff --git a/llvm/test/Transforms/InstCombine/binop-select-cast-of-select-cond.ll b/llvm/test/Transforms/InstCombine/binop-select-cast-of-select-cond.ll index b0da6d80d05a..7dc2fe1cb88e 100644 --- a/llvm/test/Transforms/InstCombine/binop-select-cast-of-select-cond.ll +++ b/llvm/test/Transforms/InstCombine/binop-select-cast-of-select-cond.ll @@ -232,7 +232,7 @@ define i64 @pr64669(i64 %a) { ; CHECK-LABEL: define i64 @pr64669 ; CHECK-SAME: (i64 [[A:%.*]]) { ; CHECK-NEXT: [[TMP1:%.*]] = add i64 [[A]], 1 -; CHECK-NEXT: [[ADD:%.*]] = select i1 icmp ne (ptr getelementptr inbounds (i8, ptr @b, i64 100), ptr @c), i64 [[TMP1]], i64 0 +; CHECK-NEXT: [[ADD:%.*]] = select i1 icmp ne (ptr getelementptr inbounds ([72 x i32], ptr @b, i64 0, i64 25), ptr @c), i64 [[TMP1]], i64 0 ; CHECK-NEXT: ret i64 [[ADD]] ; %mul = select i1 icmp ne (ptr getelementptr inbounds ([72 x i32], ptr @b, i64 0, i64 25), ptr @c), i64 %a, i64 0 diff --git a/llvm/test/Transforms/InstCombine/constant-fold-address-space-pointer.ll b/llvm/test/Transforms/InstCombine/constant-fold-address-space-pointer.ll index 857704f58028..dafe3900fef3 100644 --- a/llvm/test/Transforms/InstCombine/constant-fold-address-space-pointer.ll +++ b/llvm/test/Transforms/InstCombine/constant-fold-address-space-pointer.ll @@ -132,7 +132,8 @@ define i1 @constant_fold_inttoptr_null(i16 %i) { define i1 @constant_fold_ptrtoint_null() { ; CHECK-LABEL: @constant_fold_ptrtoint_null( -; CHECK-NEXT: ret i1 icmp eq (ptr addrspace(3) @g, ptr addrspace(3) null) +; CHECK-NEXT: [[X:%.*]] = icmp eq i16 ptrtoint (ptr addrspace(3) @g to i16), 0 +; CHECK-NEXT: ret i1 [[X]] ; %x = icmp eq i16 ptrtoint (ptr addrspace(3) @g to i16), ptrtoint (ptr addrspace(3) null to i16) ret i1 %x @@ -140,7 +141,8 @@ define i1 @constant_fold_ptrtoint_null() { define i1 @constant_fold_ptrtoint_null_2() { ; CHECK-LABEL: @constant_fold_ptrtoint_null_2( -; CHECK-NEXT: ret i1 icmp eq (ptr addrspace(3) @g, ptr addrspace(3) null) +; CHECK-NEXT: [[X:%.*]] = icmp eq i16 0, ptrtoint (ptr addrspace(3) @g to i16) +; CHECK-NEXT: ret i1 [[X]] ; %x = icmp eq i16 ptrtoint (ptr addrspace(3) null to i16), ptrtoint (ptr addrspace(3) @g to i16) ret i1 %x diff --git a/llvm/test/Transforms/InstCombine/getelementptr.ll b/llvm/test/Transforms/InstCombine/getelementptr.ll index e82c168ced01..e29f1a7cf006 100644 --- a/llvm/test/Transforms/InstCombine/getelementptr.ll +++ b/llvm/test/Transforms/InstCombine/getelementptr.ll @@ -537,7 +537,8 @@ define i32 @test21() { define i1 @test22() { ; CHECK-LABEL: @test22( -; CHECK-NEXT: ret i1 icmp ult (ptr getelementptr inbounds (i8, ptr @A, i64 4), ptr getelementptr (i8, ptr @B, i64 8)) +; CHECK-NEXT: [[C:%.*]] = icmp ult ptr getelementptr inbounds (i8, ptr @A, i64 4), getelementptr (i8, ptr @B, i64 8) +; CHECK-NEXT: ret i1 [[C]] ; %C = icmp ult ptr getelementptr (i32, ptr @A, i64 1), getelementptr (i32, ptr @B, i64 2) diff --git a/llvm/test/Transforms/InstCombine/hoist-xor-by-constant-from-xor-by-value.ll b/llvm/test/Transforms/InstCombine/hoist-xor-by-constant-from-xor-by-value.ll index d75dbcf9c9b9..200e7ba8e677 100644 --- a/llvm/test/Transforms/InstCombine/hoist-xor-by-constant-from-xor-by-value.ll +++ b/llvm/test/Transforms/InstCombine/hoist-xor-by-constant-from-xor-by-value.ll @@ -94,7 +94,8 @@ entry: define i16 @constantexpr2() { ; CHECK-LABEL: @constantexpr2( -; CHECK-NEXT: [[I1:%.*]] = zext i1 icmp ne (ptr getelementptr inbounds (i8, ptr @global_constant3, i64 40), ptr @global_constant4) to i16 +; CHECK-NEXT: [[I0:%.*]] = icmp ne ptr getelementptr inbounds (i8, ptr @global_constant3, i64 40), @global_constant4 +; CHECK-NEXT: [[I1:%.*]] = zext i1 [[I0]] to i16 ; CHECK-NEXT: [[I2:%.*]] = load ptr, ptr @global_constant5, align 1 ; CHECK-NEXT: [[I3:%.*]] = load i16, ptr [[I2]], align 1 ; CHECK-NEXT: [[I4:%.*]] = xor i16 [[I3]], [[I1]] diff --git a/llvm/test/Transforms/InstCombine/pr33453.ll b/llvm/test/Transforms/InstCombine/pr33453.ll index 23a232dd0b9a..45f87b753006 100644 --- a/llvm/test/Transforms/InstCombine/pr33453.ll +++ b/llvm/test/Transforms/InstCombine/pr33453.ll @@ -6,7 +6,7 @@ define float @patatino() { ; CHECK-LABEL: @patatino( -; CHECK-NEXT: [[FMUL:%.*]] = uitofp i1 mul (i1 icmp eq (ptr getelementptr inbounds (i8, ptr @g2, i64 2), ptr @g1), i1 icmp eq (ptr getelementptr inbounds (i8, ptr @g2, i64 2), ptr @g1)) to float +; CHECK-NEXT: [[FMUL:%.*]] = uitofp i1 mul (i1 icmp eq (ptr getelementptr inbounds (i16, ptr @g2, i64 1), ptr @g1), i1 icmp eq (ptr getelementptr inbounds (i16, ptr @g2, i64 1), ptr @g1)) to float ; CHECK-NEXT: ret float [[FMUL]] ; %uitofp1 = uitofp i1 icmp eq (ptr getelementptr inbounds (i16, ptr @g2, i64 1), ptr @g1) to float diff --git a/llvm/test/Transforms/InstCombine/pr83947.ll b/llvm/test/Transforms/InstCombine/pr83947.ll index 63a242abc925..c1d601ff6371 100644 --- a/llvm/test/Transforms/InstCombine/pr83947.ll +++ b/llvm/test/Transforms/InstCombine/pr83947.ll @@ -6,7 +6,7 @@ define void @masked_scatter1() { ; CHECK-LABEL: define void @masked_scatter1() { -; CHECK-NEXT: call void @llvm.masked.scatter.nxv4i32.nxv4p0( zeroinitializer, shufflevector ( insertelement ( poison, ptr @c, i64 0), poison, zeroinitializer), i32 4, shufflevector ( insertelement ( poison, i1 icmp eq (ptr getelementptr inbounds (i8, ptr @b, i64 4), ptr @c), i64 0), poison, zeroinitializer)) +; CHECK-NEXT: call void @llvm.masked.scatter.nxv4i32.nxv4p0( zeroinitializer, shufflevector ( insertelement ( poison, ptr @c, i64 0), poison, zeroinitializer), i32 4, shufflevector ( insertelement ( poison, i1 icmp eq (ptr getelementptr inbounds (i32, ptr @b, i64 1), ptr @c), i64 0), poison, zeroinitializer)) ; CHECK-NEXT: ret void ; call void @llvm.masked.scatter.nxv4i32.nxv4p0( zeroinitializer, splat (ptr @c), i32 4, splat (i1 icmp eq (ptr getelementptr (i32, ptr @b, i64 1), ptr @c))) @@ -59,7 +59,7 @@ define void @masked_scatter6() { define void @masked_scatter7() { ; CHECK-LABEL: define void @masked_scatter7() { -; CHECK-NEXT: call void @llvm.masked.scatter.v2i32.v2p0(<2 x i32> zeroinitializer, <2 x ptr> , i32 4, <2 x i1> ) +; CHECK-NEXT: call void @llvm.masked.scatter.v2i32.v2p0(<2 x i32> zeroinitializer, <2 x ptr> , i32 4, <2 x i1> ) ; CHECK-NEXT: ret void ; call void @llvm.masked.scatter.v2i32.v2p0(<2 x i32> zeroinitializer, <2 x ptr> splat (ptr @c), i32 4, <2 x i1> splat (i1 icmp eq (ptr getelementptr (i32, ptr @b, i64 1), ptr @c))) diff --git a/llvm/test/Transforms/InstCombine/rem.ll b/llvm/test/Transforms/InstCombine/rem.ll index a8fa72c37d32..ae390e72a4b7 100644 --- a/llvm/test/Transforms/InstCombine/rem.ll +++ b/llvm/test/Transforms/InstCombine/rem.ll @@ -522,7 +522,7 @@ define i32 @pr27968_0(i1 %c0, ptr %p) { ; CHECK-NEXT: [[V:%.*]] = load volatile i32, ptr [[P:%.*]], align 4 ; CHECK-NEXT: br label [[IF_END]] ; CHECK: if.end: -; CHECK-NEXT: br i1 icmp eq (ptr getelementptr inbounds (i8, ptr @a, i64 8), ptr @b), label [[REM_IS_SAFE:%.*]], label [[REM_IS_UNSAFE:%.*]] +; CHECK-NEXT: br i1 icmp eq (ptr getelementptr inbounds ([5 x i16], ptr @a, i64 0, i64 4), ptr @b), label [[REM_IS_SAFE:%.*]], label [[REM_IS_UNSAFE:%.*]] ; CHECK: rem.is.safe: ; CHECK-NEXT: ret i32 0 ; CHECK: rem.is.unsafe: @@ -591,7 +591,7 @@ define i32 @pr27968_2(i1 %c0, ptr %p) { ; CHECK-NEXT: [[V:%.*]] = load volatile i32, ptr [[P:%.*]], align 4 ; CHECK-NEXT: br label [[IF_END]] ; CHECK: if.end: -; CHECK-NEXT: br i1 icmp eq (ptr getelementptr inbounds (i8, ptr @a, i64 8), ptr @b), label [[REM_IS_SAFE:%.*]], label [[REM_IS_UNSAFE:%.*]] +; CHECK-NEXT: br i1 icmp eq (ptr getelementptr inbounds ([5 x i16], ptr @a, i64 0, i64 4), ptr @b), label [[REM_IS_SAFE:%.*]], label [[REM_IS_UNSAFE:%.*]] ; CHECK: rem.is.safe: ; CHECK-NEXT: ret i32 0 ; CHECK: rem.is.unsafe: diff --git a/llvm/test/Transforms/InstCombine/select-and-or.ll b/llvm/test/Transforms/InstCombine/select-and-or.ll index 0965e1c8348e..0f7acd4d56c0 100644 --- a/llvm/test/Transforms/InstCombine/select-and-or.ll +++ b/llvm/test/Transforms/InstCombine/select-and-or.ll @@ -431,7 +431,7 @@ define i1 @not_false_not_use3(i1 %x, i1 %y) { define i1 @demorgan_select_infloop1(i1 %L) { ; CHECK-LABEL: @demorgan_select_infloop1( ; CHECK-NEXT: [[NOT_L:%.*]] = xor i1 [[L:%.*]], true -; CHECK-NEXT: [[C15:%.*]] = select i1 [[NOT_L]], i1 xor (i1 icmp eq (ptr getelementptr inbounds (i8, ptr @g2, i64 2), ptr @g1), i1 icmp eq (ptr getelementptr inbounds (i8, ptr @g2, i64 2), ptr @g1)), i1 false +; CHECK-NEXT: [[C15:%.*]] = select i1 [[NOT_L]], i1 xor (i1 icmp eq (ptr getelementptr inbounds (i16, ptr @g2, i64 1), ptr @g1), i1 icmp eq (ptr getelementptr inbounds (i16, ptr @g2, i64 1), ptr @g1)), i1 false ; CHECK-NEXT: ret i1 [[C15]] ; %not.L = xor i1 %L, true @@ -443,7 +443,7 @@ define i1 @demorgan_select_infloop1(i1 %L) { define i1 @demorgan_select_infloop2(i1 %L) { ; CHECK-LABEL: @demorgan_select_infloop2( ; CHECK-NEXT: [[NOT_L:%.*]] = xor i1 [[L:%.*]], true -; CHECK-NEXT: [[C15:%.*]] = select i1 [[NOT_L]], i1 true, i1 xor (i1 icmp eq (ptr getelementptr inbounds (i8, ptr @g2, i64 2), ptr @g1), i1 icmp eq (ptr getelementptr inbounds (i8, ptr @g2, i64 2), ptr @g1)) +; CHECK-NEXT: [[C15:%.*]] = select i1 [[NOT_L]], i1 true, i1 xor (i1 icmp eq (ptr getelementptr inbounds (i16, ptr @g2, i64 1), ptr @g1), i1 icmp eq (ptr getelementptr inbounds (i16, ptr @g2, i64 1), ptr @g1)) ; CHECK-NEXT: ret i1 [[C15]] ; %not.L = xor i1 %L, true diff --git a/llvm/test/Transforms/InstCombine/select-safe-transforms.ll b/llvm/test/Transforms/InstCombine/select-safe-transforms.ll index f0072e24161d..1a4848934c9f 100644 --- a/llvm/test/Transforms/InstCombine/select-safe-transforms.ll +++ b/llvm/test/Transforms/InstCombine/select-safe-transforms.ll @@ -85,7 +85,7 @@ define <2 x i1> @xor_and2(<2 x i1> %c, <2 x i32> %X, <2 x i32> %Y) { define <2 x i1> @xor_and3(<2 x i1> %c, <2 x i32> %X, <2 x i32> %Y) { ; CHECK-LABEL: @xor_and3( ; CHECK-NEXT: [[COMP:%.*]] = icmp uge <2 x i32> [[X:%.*]], [[Y:%.*]] -; CHECK-NEXT: [[SEL:%.*]] = select <2 x i1> [[C:%.*]], <2 x i1> [[COMP]], <2 x i1> +; CHECK-NEXT: [[SEL:%.*]] = select <2 x i1> [[C:%.*]], <2 x i1> [[COMP]], <2 x i1> ; CHECK-NEXT: ret <2 x i1> [[SEL]] ; %comp = icmp ult <2 x i32> %X, %Y @@ -122,7 +122,7 @@ define <2 x i1> @xor_or2(<2 x i1> %c, <2 x i32> %X, <2 x i32> %Y) { define <2 x i1> @xor_or3(<2 x i1> %c, <2 x i32> %X, <2 x i32> %Y) { ; CHECK-LABEL: @xor_or3( ; CHECK-NEXT: [[COMP:%.*]] = icmp uge <2 x i32> [[X:%.*]], [[Y:%.*]] -; CHECK-NEXT: [[SEL:%.*]] = select <2 x i1> [[C:%.*]], <2 x i1> , <2 x i1> [[COMP]] +; CHECK-NEXT: [[SEL:%.*]] = select <2 x i1> [[C:%.*]], <2 x i1> , <2 x i1> [[COMP]] ; CHECK-NEXT: ret <2 x i1> [[SEL]] ; %comp = icmp ult <2 x i32> %X, %Y diff --git a/llvm/test/Transforms/InstSimplify/ConstProp/bitcast.ll b/llvm/test/Transforms/InstSimplify/ConstProp/bitcast.ll index 99b1eb6ef07d..9c75b66db50c 100644 --- a/llvm/test/Transforms/InstSimplify/ConstProp/bitcast.ll +++ b/llvm/test/Transforms/InstSimplify/ConstProp/bitcast.ll @@ -35,7 +35,8 @@ define i1 @bad_icmp_constexpr_bitcast() { define i1 @bad_fcmp_constexpr_bitcast() { ; CHECK-LABEL: @bad_fcmp_constexpr_bitcast( -; CHECK-NEXT: ret i1 fcmp oeq (float bitcast (i32 ptrtoint (ptr @c to i32) to float), float bitcast (i32 add (i32 ptrtoint (ptr @d to i32), i32 2) to float)) +; CHECK-NEXT: [[CMP:%.*]] = fcmp oeq float bitcast (i32 ptrtoint (ptr @c to i32) to float), bitcast (i32 add (i32 ptrtoint (ptr @d to i32), i32 2) to float) +; CHECK-NEXT: ret i1 [[CMP]] ; %cmp = fcmp oeq float bitcast (i32 ptrtoint (ptr @c to i32) to float), bitcast (i32 add (i32 ptrtoint (ptr @d to i32), i32 2) to float) ret i1 %cmp @@ -45,7 +46,8 @@ define i1 @bad_fcmp_constexpr_bitcast() { define i1 @fcmp_constexpr_oeq(float %conv) { ; CHECK-LABEL: @fcmp_constexpr_oeq( -; CHECK-NEXT: ret i1 fcmp oeq (float bitcast (i32 ptrtoint (ptr @a to i32) to float), float bitcast (i32 ptrtoint (ptr @a to i32) to float)) +; CHECK-NEXT: [[CMP:%.*]] = fcmp oeq float bitcast (i32 ptrtoint (ptr @a to i32) to float), bitcast (i32 ptrtoint (ptr @a to i32) to float) +; CHECK-NEXT: ret i1 [[CMP]] ; %cmp = fcmp oeq float bitcast (i32 ptrtoint (ptr @a to i32) to float), bitcast (i32 ptrtoint (ptr @a to i32) to float) ret i1 %cmp @@ -55,7 +57,8 @@ define i1 @fcmp_constexpr_oeq(float %conv) { define i1 @fcmp_constexpr_une(float %conv) { ; CHECK-LABEL: @fcmp_constexpr_une( -; CHECK-NEXT: ret i1 fcmp une (float bitcast (i32 ptrtoint (ptr @a to i32) to float), float bitcast (i32 ptrtoint (ptr @a to i32) to float)) +; CHECK-NEXT: [[CMP:%.*]] = fcmp une float bitcast (i32 ptrtoint (ptr @a to i32) to float), bitcast (i32 ptrtoint (ptr @a to i32) to float) +; CHECK-NEXT: ret i1 [[CMP]] ; %cmp = fcmp une float bitcast (i32 ptrtoint (ptr @a to i32) to float), bitcast (i32 ptrtoint (ptr @a to i32) to float) ret i1 %cmp diff --git a/llvm/test/Transforms/InstSimplify/ConstProp/icmp-global.ll b/llvm/test/Transforms/InstSimplify/ConstProp/icmp-global.ll index 1d7ed23d3e82..3ef9552eb79d 100644 --- a/llvm/test/Transforms/InstSimplify/ConstProp/icmp-global.ll +++ b/llvm/test/Transforms/InstSimplify/ConstProp/icmp-global.ll @@ -47,7 +47,8 @@ define i1 @ule_constexpr_null(ptr %x) { define i1 @slt_constexpr_null(ptr %x) { ; CHECK-LABEL: @slt_constexpr_null( -; CHECK-NEXT: ret i1 icmp slt (ptr @ugt_null_constexpr, ptr null) +; CHECK-NEXT: [[CMP:%.*]] = icmp slt ptr @ugt_null_constexpr, null +; CHECK-NEXT: ret i1 [[CMP]] ; %cmp = icmp slt ptr @ugt_null_constexpr, null ret i1 %cmp @@ -57,7 +58,8 @@ define i1 @slt_constexpr_null(ptr %x) { define i1 @ult_constexpr_constexpr_one(ptr %x) { ; CHECK-LABEL: @ult_constexpr_constexpr_one( -; CHECK-NEXT: ret i1 icmp ugt (ptr inttoptr (i32 1 to ptr), ptr @ugt_null_constexpr) +; CHECK-NEXT: [[CMP:%.*]] = icmp ult ptr @ugt_null_constexpr, inttoptr (i32 1 to ptr) +; CHECK-NEXT: ret i1 [[CMP]] ; %cmp = icmp ult ptr @ugt_null_constexpr, inttoptr (i32 1 to ptr) ret i1 %cmp @@ -86,7 +88,8 @@ define i1 @global_ugt_null() { define i1 @global_sgt_null() { ; CHECK-LABEL: @global_sgt_null( -; CHECK-NEXT: ret i1 icmp sgt (ptr @g, ptr null) +; CHECK-NEXT: [[CMP:%.*]] = icmp sgt ptr @g, null +; CHECK-NEXT: ret i1 [[CMP]] ; %cmp = icmp sgt ptr @g, null ret i1 %cmp @@ -95,7 +98,8 @@ define i1 @global_sgt_null() { ; Should not fold to true, as the gep computes a null value. define i1 @global_out_of_bounds_gep_ne_null() { ; CHECK-LABEL: @global_out_of_bounds_gep_ne_null( -; CHECK-NEXT: ret i1 icmp ne (ptr getelementptr (i8, ptr @g3, i64 sub (i64 0, i64 ptrtoint (ptr @g3 to i64))), ptr null) +; CHECK-NEXT: [[CMP:%.*]] = icmp ne ptr getelementptr (i8, ptr @g3, i64 sub (i64 0, i64 ptrtoint (ptr @g3 to i64))), null +; CHECK-NEXT: ret i1 [[CMP]] ; %cmp = icmp ne ptr getelementptr (i8, ptr @g3, i64 sub (i64 0, i64 ptrtoint (ptr @g3 to i64))), null ret i1 %cmp @@ -121,7 +125,8 @@ define i1 @global_gep_ugt_null() { define i1 @global_gep_sgt_null() { ; CHECK-LABEL: @global_gep_sgt_null( -; CHECK-NEXT: ret i1 icmp sgt (ptr getelementptr inbounds (i8, ptr @g, i64 8), ptr null) +; CHECK-NEXT: [[CMP:%.*]] = icmp sgt ptr getelementptr inbounds (i8, ptr @g, i64 8), null +; CHECK-NEXT: ret i1 [[CMP]] ; %gep = getelementptr inbounds [2 x i32], ptr @g, i64 1 %cmp = icmp sgt ptr %gep, null @@ -132,7 +137,8 @@ define i1 @global_gep_sgt_null() { ; are equal. define i1 @null_gep_ne_null() { ; CHECK-LABEL: @null_gep_ne_null( -; CHECK-NEXT: ret i1 icmp ne (ptr getelementptr (i8, ptr null, i64 ptrtoint (ptr @g2_weak to i64)), ptr null) +; CHECK-NEXT: [[CMP:%.*]] = icmp ne ptr getelementptr (i8, ptr null, i64 ptrtoint (ptr @g2_weak to i64)), null +; CHECK-NEXT: ret i1 [[CMP]] ; %gep = getelementptr i8, ptr null, i64 ptrtoint (ptr @g2_weak to i64) %cmp = icmp ne ptr %gep, null @@ -141,7 +147,8 @@ define i1 @null_gep_ne_null() { define i1 @null_gep_ugt_null() { ; CHECK-LABEL: @null_gep_ugt_null( -; CHECK-NEXT: ret i1 icmp ugt (ptr getelementptr (i8, ptr null, i64 ptrtoint (ptr @g2_weak to i64)), ptr null) +; CHECK-NEXT: [[CMP:%.*]] = icmp ugt ptr getelementptr (i8, ptr null, i64 ptrtoint (ptr @g2_weak to i64)), null +; CHECK-NEXT: ret i1 [[CMP]] ; %gep = getelementptr i8, ptr null, i64 ptrtoint (ptr @g2_weak to i64) %cmp = icmp ugt ptr %gep, null @@ -150,7 +157,8 @@ define i1 @null_gep_ugt_null() { define i1 @null_gep_sgt_null() { ; CHECK-LABEL: @null_gep_sgt_null( -; CHECK-NEXT: ret i1 icmp sgt (ptr getelementptr (i8, ptr null, i64 ptrtoint (ptr @g2_weak to i64)), ptr null) +; CHECK-NEXT: [[CMP:%.*]] = icmp sgt ptr getelementptr (i8, ptr null, i64 ptrtoint (ptr @g2_weak to i64)), null +; CHECK-NEXT: ret i1 [[CMP]] ; %gep = getelementptr i8, ptr null, i64 ptrtoint (ptr @g2_weak to i64) %cmp = icmp sgt ptr %gep, null @@ -177,7 +185,8 @@ define i1 @null_gep_ugt_null_constant_int() { define i1 @null_gep_ne_global() { ; CHECK-LABEL: @null_gep_ne_global( -; CHECK-NEXT: ret i1 icmp ne (ptr getelementptr (i8, ptr null, i64 ptrtoint (ptr @g3 to i64)), ptr @g3) +; CHECK-NEXT: [[CMP:%.*]] = icmp ne ptr getelementptr (i8, ptr null, i64 ptrtoint (ptr @g3 to i64)), @g3 +; CHECK-NEXT: ret i1 [[CMP]] ; %gep = getelementptr i8, ptr null, i64 ptrtoint (ptr @g3 to i64) %cmp = icmp ne ptr %gep, @g3 @@ -186,7 +195,8 @@ define i1 @null_gep_ne_global() { define i1 @null_gep_ult_global() { ; CHECK-LABEL: @null_gep_ult_global( -; CHECK-NEXT: ret i1 icmp ult (ptr getelementptr (i8, ptr null, i64 ptrtoint (ptr @g3 to i64)), ptr @g3) +; CHECK-NEXT: [[CMP:%.*]] = icmp ult ptr getelementptr (i8, ptr null, i64 ptrtoint (ptr @g3 to i64)), @g3 +; CHECK-NEXT: ret i1 [[CMP]] ; %gep = getelementptr i8, ptr null, i64 ptrtoint (ptr @g3 to i64) %cmp = icmp ult ptr %gep, @g3 @@ -195,7 +205,8 @@ define i1 @null_gep_ult_global() { define i1 @null_gep_slt_global() { ; CHECK-LABEL: @null_gep_slt_global( -; CHECK-NEXT: ret i1 icmp slt (ptr getelementptr ([2 x i32], ptr null, i64 ptrtoint (ptr @g2 to i64)), ptr @g) +; CHECK-NEXT: [[CMP:%.*]] = icmp slt ptr getelementptr ([2 x i32], ptr null, i64 ptrtoint (ptr @g2 to i64)), @g +; CHECK-NEXT: ret i1 [[CMP]] ; %gep = getelementptr [2 x i32], ptr null, i64 ptrtoint (ptr @g2 to i64) %cmp = icmp slt ptr %gep, @g @@ -222,7 +233,8 @@ define i1 @global_gep_ugt_global() { define i1 @global_gep_sgt_global() { ; CHECK-LABEL: @global_gep_sgt_global( -; CHECK-NEXT: ret i1 icmp sgt (ptr getelementptr inbounds (i8, ptr @g, i64 8), ptr @g) +; CHECK-NEXT: [[CMP:%.*]] = icmp sgt ptr getelementptr inbounds (i8, ptr @g, i64 8), @g +; CHECK-NEXT: ret i1 [[CMP]] ; %gep = getelementptr inbounds [2 x i32], ptr @g, i64 1 %cmp = icmp sgt ptr %gep, @g @@ -232,7 +244,8 @@ define i1 @global_gep_sgt_global() { ; This should not fold to true, as the offset is negative. define i1 @global_gep_ugt_global_neg_offset() { ; CHECK-LABEL: @global_gep_ugt_global_neg_offset( -; CHECK-NEXT: ret i1 icmp ugt (ptr getelementptr (i8, ptr @g, i64 -8), ptr @g) +; CHECK-NEXT: [[CMP:%.*]] = icmp ugt ptr getelementptr (i8, ptr @g, i64 -8), @g +; CHECK-NEXT: ret i1 [[CMP]] ; %gep = getelementptr [2 x i32], ptr @g, i64 -1 %cmp = icmp ugt ptr %gep, @g @@ -241,7 +254,8 @@ define i1 @global_gep_ugt_global_neg_offset() { define i1 @global_gep_sgt_global_neg_offset() { ; CHECK-LABEL: @global_gep_sgt_global_neg_offset( -; CHECK-NEXT: ret i1 icmp sgt (ptr getelementptr (i8, ptr @g, i64 -8), ptr @g) +; CHECK-NEXT: [[CMP:%.*]] = icmp sgt ptr getelementptr (i8, ptr @g, i64 -8), @g +; CHECK-NEXT: ret i1 [[CMP]] ; %gep = getelementptr [2 x i32], ptr @g, i64 -1 %cmp = icmp sgt ptr %gep, @g @@ -260,7 +274,8 @@ define i1 @global_gep_ugt_global_gep() { ; Should not fold due to signed comparison. define i1 @global_gep_sgt_global_gep() { ; CHECK-LABEL: @global_gep_sgt_global_gep( -; CHECK-NEXT: ret i1 icmp sgt (ptr getelementptr inbounds (i8, ptr @g, i64 4), ptr @g) +; CHECK-NEXT: [[CMP:%.*]] = icmp sgt ptr getelementptr inbounds (i8, ptr @g, i64 4), @g +; CHECK-NEXT: ret i1 [[CMP]] ; %gep2 = getelementptr inbounds [2 x i32], ptr @g, i64 0, i64 1 %cmp = icmp sgt ptr %gep2, @g @@ -280,7 +295,8 @@ declare void @func() define i1 @global_no_cfi() { ; CHECK-LABEL: @global_no_cfi( -; CHECK-NEXT: ret i1 icmp eq (ptr @func, ptr no_cfi @func) +; CHECK-NEXT: [[CMP:%.*]] = icmp eq ptr @func, no_cfi @func +; CHECK-NEXT: ret i1 [[CMP]] ; %cmp = icmp eq ptr @func, no_cfi @func ret i1 %cmp @@ -290,7 +306,8 @@ define i1 @blockaddr_no_cfi() { ; CHECK-LABEL: @blockaddr_no_cfi( ; CHECK-NEXT: br label [[BB:%.*]] ; CHECK: bb: -; CHECK-NEXT: ret i1 icmp eq (ptr blockaddress(@blockaddr_no_cfi, [[BB]]), ptr no_cfi @func) +; CHECK-NEXT: [[CMP:%.*]] = icmp eq ptr blockaddress(@blockaddr_no_cfi, [[BB]]), no_cfi @func +; CHECK-NEXT: ret i1 [[CMP]] ; br label %bb @@ -301,7 +318,8 @@ bb: define i1 @global_no_cfi_dso_local_equivalent() { ; CHECK-LABEL: @global_no_cfi_dso_local_equivalent( -; CHECK-NEXT: ret i1 icmp eq (ptr dso_local_equivalent @func, ptr no_cfi @func) +; CHECK-NEXT: [[CMP:%.*]] = icmp eq ptr dso_local_equivalent @func, no_cfi @func +; CHECK-NEXT: ret i1 [[CMP]] ; %cmp = icmp eq ptr dso_local_equivalent @func, no_cfi @func ret i1 %cmp diff --git a/llvm/test/Transforms/InstSimplify/bitcast-vector-fold.ll b/llvm/test/Transforms/InstSimplify/bitcast-vector-fold.ll index b9e2753d3feb..68ff0859beb2 100644 --- a/llvm/test/Transforms/InstSimplify/bitcast-vector-fold.ll +++ b/llvm/test/Transforms/InstSimplify/bitcast-vector-fold.ll @@ -76,7 +76,8 @@ define <4 x i32> @test9(<1 x i64> %y) { define <1 x i1> @test10() { ; CHECK-LABEL: @test10( -; CHECK-NEXT: ret <1 x i1> to i64), i64 0)> +; CHECK-NEXT: [[RET:%.*]] = icmp eq <1 x i64> to i64)>, zeroinitializer +; CHECK-NEXT: ret <1 x i1> [[RET]] ; %ret = icmp eq <1 x i64> to i64)>, zeroinitializer ret <1 x i1> %ret diff --git a/llvm/test/Transforms/InstSimplify/compare.ll b/llvm/test/Transforms/InstSimplify/compare.ll index 0f72cd813f2f..1e78bb232f79 100644 --- a/llvm/test/Transforms/InstSimplify/compare.ll +++ b/llvm/test/Transforms/InstSimplify/compare.ll @@ -3078,7 +3078,8 @@ define i1 @globals_inequal() { ; TODO: Never equal define i1 @globals_offset_inequal() { ; CHECK-LABEL: @globals_offset_inequal( -; CHECK-NEXT: ret i1 icmp ne (ptr getelementptr inbounds (i8, ptr @A, i32 1), ptr getelementptr inbounds (i8, ptr @B, i32 1)) +; CHECK-NEXT: [[RES:%.*]] = icmp ne ptr getelementptr inbounds (i8, ptr @A, i32 1), getelementptr inbounds (i8, ptr @B, i32 1) +; CHECK-NEXT: ret i1 [[RES]] ; %a.off = getelementptr i8, ptr @A, i32 1 %b.off = getelementptr i8, ptr @B, i32 1 @@ -3100,7 +3101,8 @@ define i1 @test_byval_global_inequal(ptr byval(i32) %a) { define i1 @neg_global_alias() { ; CHECK-LABEL: @neg_global_alias( -; CHECK-NEXT: ret i1 icmp ne (ptr @A, ptr @A.alias) +; CHECK-NEXT: [[RES:%.*]] = icmp ne ptr @A, @A.alias +; CHECK-NEXT: ret i1 [[RES]] ; %res = icmp ne ptr @A, @A.alias ret i1 %res diff --git a/llvm/test/Transforms/InstSimplify/past-the-end.ll b/llvm/test/Transforms/InstSimplify/past-the-end.ll index 1e146d18327a..cc2fe6f36fcd 100644 --- a/llvm/test/Transforms/InstSimplify/past-the-end.ll +++ b/llvm/test/Transforms/InstSimplify/past-the-end.ll @@ -21,7 +21,8 @@ define zeroext i1 @no_offsets() { define zeroext i1 @both_past_the_end() { ; CHECK-LABEL: @both_past_the_end( -; CHECK-NEXT: ret i1 icmp eq (ptr getelementptr inbounds (i8, ptr @opte_a, i32 4), ptr getelementptr inbounds (i8, ptr @opte_b, i32 4)) +; CHECK-NEXT: [[T:%.*]] = icmp eq ptr getelementptr inbounds (i8, ptr @opte_a, i32 4), getelementptr inbounds (i8, ptr @opte_b, i32 4) +; CHECK-NEXT: ret i1 [[T]] ; %x = getelementptr i32, ptr @opte_a, i32 1 %y = getelementptr i32, ptr @opte_b, i32 1 @@ -35,7 +36,8 @@ define zeroext i1 @both_past_the_end() { define zeroext i1 @just_one_past_the_end() { ; CHECK-LABEL: @just_one_past_the_end( -; CHECK-NEXT: ret i1 icmp eq (ptr getelementptr inbounds (i8, ptr @opte_a, i32 4), ptr @opte_b) +; CHECK-NEXT: [[T:%.*]] = icmp eq ptr getelementptr inbounds (i8, ptr @opte_a, i32 4), @opte_b +; CHECK-NEXT: ret i1 [[T]] ; %x = getelementptr i32, ptr @opte_a, i32 1 %t = icmp eq ptr %x, @opte_b diff --git a/llvm/test/Transforms/JumpThreading/constant-fold-status.ll b/llvm/test/Transforms/JumpThreading/constant-fold-status.ll index ae984df1caa3..3d98b0d6eecc 100644 --- a/llvm/test/Transforms/JumpThreading/constant-fold-status.ll +++ b/llvm/test/Transforms/JumpThreading/constant-fold-status.ll @@ -8,7 +8,8 @@ ; status check that is hidden under EXPENSIVE_CHECKS. ; CHECK-LABEL: entry: -; CHECK-NEXT: br i1 icmp eq (i32 ptrtoint (ptr @a to i32), i32 0), label %overflow, label %cont +; CHECK-NEXT: %.not = icmp eq i32 ptrtoint (ptr @a to i32), 0 +; CHECK-NEXT: br i1 %.not, label %overflow, label %cont @a = internal global i16 0 diff --git a/llvm/test/Transforms/LowerTypeTests/cfi-direct-call1.ll b/llvm/test/Transforms/LowerTypeTests/cfi-direct-call1.ll index 1b7039f905cc..3afb4875ca28 100644 --- a/llvm/test/Transforms/LowerTypeTests/cfi-direct-call1.ll +++ b/llvm/test/Transforms/LowerTypeTests/cfi-direct-call1.ll @@ -56,8 +56,9 @@ entry: ; FULL: %fptr1 = select i1 %cmp.i, ptr @local_func1, ptr @local_func2 ; Indirect references to extern_weak and extern_decl must go through jump table -; FULL: %0 = select i1 icmp ne (ptr @extern_weak, ptr null), ptr getelementptr inbounds ([4 x [8 x i8]], ptr @.cfi.jumptable, i64 0, i64 2), ptr null -; FULL: %fptr2 = select i1 %cmp.i, ptr %0, ptr getelementptr inbounds ([4 x [8 x i8]], ptr @.cfi.jumptable, i64 0, i64 3) +; FULL: [[CMP:%.*]] = icmp ne ptr @extern_weak, null +; FULL: [[SEL:%.*]] = select i1 [[CMP]], ptr getelementptr inbounds ([4 x [8 x i8]], ptr @.cfi.jumptable, i64 0, i64 2), ptr null +; FULL: %fptr2 = select i1 %cmp.i, ptr [[SEL]], ptr getelementptr inbounds ([4 x [8 x i8]], ptr @.cfi.jumptable, i64 0, i64 3) ; Direct calls to extern_weak and extern_decl should go to original names ; FULL: %call5 = tail call i32 @extern_decl() @@ -83,8 +84,9 @@ entry: ; THIN: %fptr1 = select i1 %cmp.i, ptr @local_func1, ptr @local_func2 ; Indirect references to extern_weak and extern_decl must go through jump table -; THIN: %0 = select i1 icmp ne (ptr @extern_weak, ptr null), ptr @extern_weak.cfi_jt, ptr null -; THIN: %fptr2 = select i1 %cmp.i, ptr %0, ptr @extern_decl.cfi_jt +; THIN: [[CMP:%.*]] = icmp ne ptr @extern_weak, null +; THIN: [[SEL:%.*]] = select i1 [[CMP]], ptr @extern_weak.cfi_jt, ptr null +; THIN: %fptr2 = select i1 %cmp.i, ptr [[SEL]], ptr @extern_decl.cfi_jt ; Direct calls to extern_weak and extern_decl should go to original names ; THIN: %call5 = tail call i32 @extern_decl() diff --git a/llvm/test/Transforms/LowerTypeTests/function-weak.ll b/llvm/test/Transforms/LowerTypeTests/function-weak.ll index 5f9041cd21b3..33876bda356c 100644 --- a/llvm/test/Transforms/LowerTypeTests/function-weak.ll +++ b/llvm/test/Transforms/LowerTypeTests/function-weak.ll @@ -34,9 +34,10 @@ declare !type !0 extern_weak void @f() ; CHECK: define zeroext i1 @check_f() define zeroext i1 @check_f() { entry: -; CHECK: %0 = select i1 icmp ne (ptr @f, ptr null), ptr @[[JT:.*]], ptr null -; CHECK: %1 = icmp ne ptr %0, null -; ret i1 %1 +; CHECK: [[CMP:%.*]] = icmp ne ptr @f, null +; CHECK: [[SEL:%.*]] = select i1 [[CMP]], ptr @[[JT:.*]], ptr null +; CHECK: [[CMP2:%.*]] = icmp ne ptr [[SEL]], null +; CHECK: ret i1 [[CMP2]] ret i1 icmp ne (ptr @f, ptr null) } @@ -50,11 +51,12 @@ entry: define void @struct() { ; CHECK-LABEL: define void @struct() { -; CHECK: %0 = select i1 icmp ne (ptr @f, ptr null), ptr @.cfi.jumptable, ptr null -; CHECK-NEXT: %1 = icmp ne ptr %0, null -; CHECK-NEXT: %2 = insertvalue { i1, i8 } poison, i1 %1, 0 -; CHECK-NEXT: %3 = insertvalue { i1, i8 } %2, i8 0, 1 -; CHECK-NEXT: %x = extractvalue { i1, i8 } %3, 0 +; CHECK: [[CMP:%.*]] = icmp ne ptr @f, null +; CHECK: [[SEL:%.*]] = select i1 [[CMP]], ptr @.cfi.jumptable, ptr null +; CHECK-NEXT: [[CMP2:%.*]] = icmp ne ptr [[SEL]], null +; CHECK-NEXT: [[IV:%.*]] = insertvalue { i1, i8 } poison, i1 [[CMP2]], 0 +; CHECK-NEXT: [[IV2:%.*]] = insertvalue { i1, i8 } [[IV]], i8 0, 1 +; CHECK-NEXT: %x = extractvalue { i1, i8 } [[IV2]], 0 entry: %x = extractvalue { i1, i8 } { i1 icmp ne (ptr @f, ptr null), i8 0 }, 0 @@ -64,14 +66,16 @@ entry: define void @phi(i1 %c) { ; CHECK-LABEL: define void @phi(i1 %c) { ; CHECK: entry: -; CHECK: %0 = select i1 icmp ne (ptr @f, ptr null), ptr @.cfi.jumptable, ptr null +; CHECK: [[CMP:%.*]] = icmp ne ptr @f, null +; CHECK: [[SEL:%.*]] = select i1 [[CMP]], ptr @.cfi.jumptable, ptr null ; CHECK: br i1 %c, label %if, label %join ; CHECK: if: -; CHECK: %1 = select i1 icmp ne (ptr @f, ptr null), ptr @.cfi.jumptable, ptr null +; CHECK: [[CMP2:%.*]] = icmp ne ptr @f, null +; CHECK: [[SEL2:%.*]] = select i1 [[CMP2]], ptr @.cfi.jumptable, ptr null ; CHECK: br label %join ; CHECK: join: -; CHECK: %phi = phi ptr [ %1, %if ], [ null, %entry ] -; CHECK: %phi2 = phi ptr [ null, %if ], [ %0, %entry ] +; CHECK: %phi = phi ptr [ [[SEL2]], %if ], [ null, %entry ] +; CHECK: %phi2 = phi ptr [ null, %if ], [ [[SEL]], %entry ] entry: br i1 %c, label %if, label %join @@ -90,17 +94,19 @@ define void @phi2(i1 %c, i32 %x) { ; CHECK: entry: ; CHECK: br i1 %c, label %if, label %else ; CHECK: if: ; preds = %entry -; CHECK: %0 = select i1 icmp ne (ptr @f, ptr null), ptr @.cfi.jumptable, ptr null +; CHECK: [[CMP:%.*]] = icmp ne ptr @f, null +; CHECK: [[SEL:%.*]] = select i1 [[CMP]], ptr @.cfi.jumptable, ptr null ; CHECK: switch i32 %x, label %join [ ; CHECK: i32 0, label %join ; CHECK: ] ; CHECK: else: ; preds = %entry -; CHECK: %1 = select i1 icmp ne (ptr @f, ptr null), ptr @.cfi.jumptable, ptr null +; CHECK: [[CMP2:%.*]] = icmp ne ptr @f, null +; CHECK: [[SEL2:%.*]] = select i1 [[CMP2]], ptr @.cfi.jumptable, ptr null ; CHECK: switch i32 %x, label %join [ ; CHECK: i32 0, label %join ; CHECK: ] ; CHECK: join: ; preds = %else, %else, %if, %if -; CHECK: %phi2 = phi ptr [ %0, %if ], [ %0, %if ], [ %1, %else ], [ %1, %else ] +; CHECK: %phi2 = phi ptr [ [[SEL]], %if ], [ [[SEL]], %if ], [ [[SEL2]], %else ], [ [[SEL2]], %else ] entry: br i1 %c, label %if, label %else @@ -132,23 +138,29 @@ define i1 @foo(ptr %p) { ; RISCV: define private void @[[JT]]() #{{.*}} align 8 { ; LOONGARCH64: define private void @[[JT]]() #{{.*}} align 8 { -; CHECK: define internal void @__cfi_global_var_init() section ".text.startup" { +; CHECK-LABEL: define internal void @__cfi_global_var_init() section ".text.startup" { ; CHECK-NEXT: entry: -; CHECK-NEXT: %0 = select i1 icmp ne (ptr @f, ptr null), ptr @[[JT]], ptr null -; CHECK-NEXT: store ptr %0, ptr @x, align 8 -; CHECK-NEXT: %1 = select i1 icmp ne (ptr @f, ptr null), ptr @[[JT]], ptr null -; CHECK-NEXT: store ptr %1, ptr @x2, align 8 -; CHECK-NEXT: %2 = select i1 icmp ne (ptr @f, ptr null), ptr @[[JT]], ptr null -; CHECK-NEXT: store ptr %2, ptr @x3, align 8 -; CHECK-NEXT: %3 = select i1 icmp ne (ptr @f, ptr null), ptr @[[JT]], ptr null -; CHECK-NEXT: %4 = getelementptr i8, ptr %3, i64 42 -; CHECK-NEXT: store ptr %4, ptr @x4, align 8 -; CHECK-NEXT: %5 = select i1 icmp ne (ptr @f, ptr null), ptr @[[JT]], ptr null -; CHECK-NEXT: %6 = insertvalue { ptr, ptr, i32 } poison, ptr %5, 0 -; CHECK-NEXT: %7 = select i1 icmp ne (ptr @f, ptr null), ptr @[[JT]], ptr null -; CHECK-NEXT: %8 = insertvalue { ptr, ptr, i32 } %6, ptr %7, 1 -; CHECK-NEXT: %9 = insertvalue { ptr, ptr, i32 } %8, i32 42, 2 -; CHECK-NEXT: store { ptr, ptr, i32 } %9, ptr @s, align 8 +; CHECK-NEXT: [[CMP:%.*]] = icmp ne ptr @f, null +; CHECK-NEXT: [[SEL:%.*]] = select i1 [[CMP]], ptr @[[JT]], ptr null +; CHECK-NEXT: store ptr [[SEL]], ptr @x, align 8 +; CHECK-NEXT: [[CMP2:%.*]] = icmp ne ptr @f, null +; CHECK-NEXT: [[SEL2:%.*]] = select i1 [[CMP2]], ptr @[[JT]], ptr null +; CHECK-NEXT: store ptr [[SEL2]], ptr @x2, align 8 +; CHECK-NEXT: [[CMP3:%.*]] = icmp ne ptr @f, null +; CHECK-NEXT: [[SEL3:%.*]] = select i1 [[CMP3]], ptr @[[JT]], ptr null +; CHECK-NEXT: store ptr [[SEL3]], ptr @x3, align 8 +; CHECK-NEXT: [[CMP4:%.*]] = icmp ne ptr @f, null +; CHECK-NEXT: [[SEL4:%.*]] = select i1 [[CMP4]], ptr @[[JT]], ptr null +; CHECK-NEXT: [[GEP:%.*]] = getelementptr i8, ptr [[SEL4]], i64 42 +; CHECK-NEXT: store ptr [[GEP]], ptr @x4, align 8 +; CHECK-NEXT: [[CMP5:%.*]] = icmp ne ptr @f, null +; CHECK-NEXT: [[SEL5:%.*]] = select i1 [[CMP5]], ptr @[[JT]], ptr null +; CHECK-NEXT: [[IV:%.*]] = insertvalue { ptr, ptr, i32 } poison, ptr [[SEL5]], 0 +; CHECK-NEXT: [[CMP6:%.*]] = icmp ne ptr @f, null +; CHECK-NEXT: [[SEL6:%.*]] = select i1 [[CMP6]], ptr @[[JT]], ptr null +; CHECK-NEXT: [[IV2:%.*]] = insertvalue { ptr, ptr, i32 } [[IV]], ptr [[SEL6]], 1 +; CHECK-NEXT: [[IV3:%.*]] = insertvalue { ptr, ptr, i32 } [[IV2]], i32 42, 2 +; CHECK-NEXT: store { ptr, ptr, i32 } [[IV3]], ptr @s, align 8 ; CHECK-NEXT: ret void ; CHECK-NEXT: } diff --git a/llvm/test/Transforms/SCCP/conditions-ranges.ll b/llvm/test/Transforms/SCCP/conditions-ranges.ll index 25719d2bee52..bb3764160f72 100644 --- a/llvm/test/Transforms/SCCP/conditions-ranges.ll +++ b/llvm/test/Transforms/SCCP/conditions-ranges.ll @@ -631,10 +631,13 @@ false: define void @f14_constexpr2() { ; CHECK-LABEL: @f14_constexpr2( ; CHECK-NEXT: entry: -; CHECK-NEXT: br i1 icmp eq (i32 ptrtoint (ptr @A to i32), i32 ptrtoint (ptr @B to i32)), label [[TRUE:%.*]], label [[FALSE:%.*]] +; CHECK-NEXT: [[BC_1:%.*]] = icmp eq i32 ptrtoint (ptr @A to i32), ptrtoint (ptr @B to i32) +; CHECK-NEXT: br i1 [[BC_1]], label [[TRUE:%.*]], label [[FALSE:%.*]] ; CHECK: true: -; CHECK-NEXT: call void @use(i1 icmp ne (i32 ptrtoint (ptr @B to i32), i32 ptrtoint (ptr @A to i32))) -; CHECK-NEXT: call void @use(i1 icmp eq (i32 ptrtoint (ptr @B to i32), i32 ptrtoint (ptr @A to i32))) +; CHECK-NEXT: [[F_1:%.*]] = icmp ne i32 ptrtoint (ptr @B to i32), ptrtoint (ptr @A to i32) +; CHECK-NEXT: call void @use(i1 [[F_1]]) +; CHECK-NEXT: [[F_2:%.*]] = icmp eq i32 ptrtoint (ptr @B to i32), ptrtoint (ptr @A to i32) +; CHECK-NEXT: call void @use(i1 [[F_2]]) ; CHECK-NEXT: ret void ; CHECK: false: ; CHECK-NEXT: ret void diff --git a/llvm/test/Transforms/SimplifyCFG/phi-to-select-constexpr-icmp.ll b/llvm/test/Transforms/SimplifyCFG/phi-to-select-constexpr-icmp.ll index 307de76bc321..a56e7041bf2e 100644 --- a/llvm/test/Transforms/SimplifyCFG/phi-to-select-constexpr-icmp.ll +++ b/llvm/test/Transforms/SimplifyCFG/phi-to-select-constexpr-icmp.ll @@ -8,7 +8,7 @@ define i1 @test(i1 %c) { ; CHECK-LABEL: @test( ; CHECK-NEXT: entry: -; CHECK-NEXT: [[SPEC_SELECT:%.*]] = select i1 [[C:%.*]], i1 false, i1 icmp ugt (ptr inttoptr (i64 -40 to ptr), ptr @glob) +; CHECK-NEXT: [[SPEC_SELECT:%.*]] = select i1 [[C:%.*]], i1 false, i1 icmp ult (ptr @glob, ptr inttoptr (i64 -40 to ptr)) ; CHECK-NEXT: ret i1 [[SPEC_SELECT]] ; entry: -- GitLab From 89e1f7784be40bea96d5e65919ce8d34151c1d69 Mon Sep 17 00:00:00 2001 From: Carlos Alberto Enciso Date: Wed, 22 May 2024 07:09:50 +0100 Subject: [PATCH 072/452] [indvars] Missing variables at Og (#88270) https://bugs.llvm.org/show_bug.cgi?id=51735 https://github.com/llvm/llvm-project/issues/51077 In the given test case: ``` 4 ... 5 void bar() { 6 int End = 777; 7 int Index = 27; 8 char Var = 1; 9 for (; Index < End; ++Index) 10 ; 11 nop(Index); 12 } 13 ... ``` Missing local variable `Index` after loop `Induction Variable Elimination`. When adding a breakpoint at line `11`, LLDB does not have information on the variable. But it has info on `Var` and `End`. --- llvm/include/llvm/Analysis/LoopInfo.h | 25 ++++ .../include/llvm/Transforms/Utils/LoopUtils.h | 6 + llvm/lib/Transforms/Utils/LoopUtils.cpp | 65 +++++++++ .../Transforms/IndVarSimplify/pr51735-1.ll | 129 +++++++++++++++++ .../Transforms/IndVarSimplify/pr51735-2.ll | 128 +++++++++++++++++ .../Transforms/IndVarSimplify/pr51735-3.ll | 131 ++++++++++++++++++ .../test/Transforms/IndVarSimplify/pr51735.ll | 104 ++++++++++++++ 7 files changed, 588 insertions(+) create mode 100644 llvm/test/Transforms/IndVarSimplify/pr51735-1.ll create mode 100644 llvm/test/Transforms/IndVarSimplify/pr51735-2.ll create mode 100644 llvm/test/Transforms/IndVarSimplify/pr51735-3.ll create mode 100644 llvm/test/Transforms/IndVarSimplify/pr51735.ll diff --git a/llvm/include/llvm/Analysis/LoopInfo.h b/llvm/include/llvm/Analysis/LoopInfo.h index 52084630560c..28c888f0c9a1 100644 --- a/llvm/include/llvm/Analysis/LoopInfo.h +++ b/llvm/include/llvm/Analysis/LoopInfo.h @@ -17,7 +17,9 @@ #include "llvm/ADT/SmallVector.h" #include "llvm/IR/CFG.h" #include "llvm/IR/Instructions.h" +#include "llvm/IR/IntrinsicInst.h" #include "llvm/IR/PassManager.h" +#include "llvm/IR/ValueHandle.h" #include "llvm/Pass.h" #include "llvm/Support/GenericLoopInfo.h" #include @@ -392,6 +394,22 @@ public: return ""; } + /// Preserve the induction variable exit value and its debug users by the + /// 'indvars' pass if the loop can deleted. Those debug users will be used + /// by the 'loop-delete' pass. + void preserveDebugInductionVariableInfo( + Value *FinalValue, + const SmallVectorImpl &DbgUsers) { + IndVarFinalValue = FinalValue; + for (auto &DebugUser : DbgUsers) + IndVarDebugUsers.push_back(DebugUser); + } + + Value *getDebugInductionVariableFinalValue() { return IndVarFinalValue; } + SmallVector &getDebugInductionVariableDebugUsers() { + return IndVarDebugUsers; + } + private: Loop() = default; @@ -399,6 +417,13 @@ private: friend class LoopBase; explicit Loop(BasicBlock *BB) : LoopBase(BB) {} ~Loop() = default; + + // Induction variable exit value and its debug users, preserved by the + // 'indvars' pass, when it detects that the loop can be deleted and the + // there are no PHIs to be rewritten. + // For now, we only preserve single induction variables. + Value *IndVarFinalValue = nullptr; + SmallVector IndVarDebugUsers; }; // Implementation in Support/GenericLoopInfoImpl.h diff --git a/llvm/include/llvm/Transforms/Utils/LoopUtils.h b/llvm/include/llvm/Transforms/Utils/LoopUtils.h index 345e09dce0b2..15b230ba92dd 100644 --- a/llvm/include/llvm/Transforms/Utils/LoopUtils.h +++ b/llvm/include/llvm/Transforms/Utils/LoopUtils.h @@ -468,6 +468,12 @@ int rewriteLoopExitValues(Loop *L, LoopInfo *LI, TargetLibraryInfo *TLI, ReplaceExitVal ReplaceExitValue, SmallVector &DeadInsts); +/// Assign exit values to variables that use this loop variable during the loop. +void addDebugValuesToIncomingValue(BasicBlock *Successor, Value *IndVar, + PHINode *PN); +void addDebugValuesToLoopVariable(BasicBlock *Successor, Value *ExitValue, + PHINode *PN); + /// Set weights for \p UnrolledLoop and \p RemainderLoop based on weights for /// \p OrigLoop and the following distribution of \p OrigLoop iteration among \p /// UnrolledLoop and \p RemainderLoop. \p UnrolledLoop receives weights that diff --git a/llvm/lib/Transforms/Utils/LoopUtils.cpp b/llvm/lib/Transforms/Utils/LoopUtils.cpp index cc883a7dc292..0bd1e8ab1d39 100644 --- a/llvm/lib/Transforms/Utils/LoopUtils.cpp +++ b/llvm/lib/Transforms/Utils/LoopUtils.cpp @@ -31,6 +31,7 @@ #include "llvm/Analysis/ScalarEvolutionAliasAnalysis.h" #include "llvm/Analysis/ScalarEvolutionExpressions.h" #include "llvm/IR/DIBuilder.h" +#include "llvm/IR/DebugInfo.h" #include "llvm/IR/Dominators.h" #include "llvm/IR/Instructions.h" #include "llvm/IR/IntrinsicInst.h" @@ -608,6 +609,17 @@ void llvm::deleteDeadLoop(Loop *L, DominatorTree *DT, ScalarEvolution *SE, llvm::SmallVector DeadDbgVariableRecords; if (ExitBlock) { + if (ExitBlock->phis().empty()) { + // As the loop is deleted, replace the debug users with the preserved + // induction variable final value recorded by the 'indvar' pass. + Value *FinalValue = L->getDebugInductionVariableFinalValue(); + SmallVector &DbgUsers = L->getDebugInductionVariableDebugUsers(); + for (WeakVH &DebugUser : DbgUsers) + if (DebugUser) + cast(DebugUser)->replaceVariableLocationOp( + 0u, FinalValue); + } + // Given LCSSA form is satisfied, we should not have users of instructions // within the dead loop outside of the loop. However, LCSSA doesn't take // unreachable uses into account. We handle them here. @@ -1401,6 +1413,36 @@ static bool checkIsIndPhi(PHINode *Phi, Loop *L, ScalarEvolution *SE, return InductionDescriptor::isInductionPHI(Phi, L, SE, ID); } +void llvm::addDebugValuesToIncomingValue(BasicBlock *Successor, Value *IndVar, + PHINode *PN) { + SmallVector DbgUsers; + findDbgUsers(DbgUsers, IndVar); + for (auto *DebugUser : DbgUsers) { + // Skip debug-users with variadic variable locations; they will not, + // get updated, which is fine as that is the existing behaviour. + if (DebugUser->hasArgList()) + continue; + auto *Cloned = cast(DebugUser->clone()); + Cloned->replaceVariableLocationOp(0u, PN); + Cloned->insertBefore(*Successor, Successor->getFirstNonPHIIt()); + } +} + +void llvm::addDebugValuesToLoopVariable(BasicBlock *Successor, Value *ExitValue, + PHINode *PN) { + SmallVector DbgUsers; + findDbgUsers(DbgUsers, PN); + for (auto *DebugUser : DbgUsers) { + // Skip debug-users with variadic variable locations; they will not, + // get updated, which is fine as that is the existing behaviour. + if (DebugUser->hasArgList()) + continue; + auto *Cloned = cast(DebugUser->clone()); + Cloned->replaceVariableLocationOp(0u, ExitValue); + Cloned->insertBefore(*Successor, Successor->getFirstNonPHIIt()); + } +} + int llvm::rewriteLoopExitValues(Loop *L, LoopInfo *LI, TargetLibraryInfo *TLI, ScalarEvolution *SE, const TargetTransformInfo *TTI, @@ -1542,6 +1584,10 @@ int llvm::rewriteLoopExitValues(Loop *L, LoopInfo *LI, TargetLibraryInfo *TLI, (isa(Inst) || isa(Inst)) ? &*Inst->getParent()->getFirstInsertionPt() : Inst; RewritePhiSet.emplace_back(PN, i, ExitValue, InsertPt, HighCost); + + // Add debug values for the candidate PHINode incoming value. + if (BasicBlock *Successor = ExitBB->getSingleSuccessor()) + addDebugValuesToIncomingValue(Successor, PN->getIncomingValue(i), PN); } } } @@ -1600,11 +1646,30 @@ int llvm::rewriteLoopExitValues(Loop *L, LoopInfo *LI, TargetLibraryInfo *TLI, // Replace PN with ExitVal if that is legal and does not break LCSSA. if (PN->getNumIncomingValues() == 1 && LI->replacementPreservesLCSSAForm(PN, ExitVal)) { + addDebugValuesToLoopVariable(PN->getParent(), ExitVal, PN); PN->replaceAllUsesWith(ExitVal); PN->eraseFromParent(); } } + // If the loop can be deleted and there are no PHIs to be rewritten (there + // are no loop live-out values), record debug variables corresponding to the + // induction variable with their constant exit-values. Those values will be + // inserted by the 'deletion loop' logic. + if (LoopCanBeDel && RewritePhiSet.empty()) { + if (auto *IndVar = L->getInductionVariable(*SE)) { + const SCEV *PNSCEV = SE->getSCEVAtScope(IndVar, L->getParentLoop()); + if (auto *Const = dyn_cast(PNSCEV)) { + Value *FinalIVValue = Const->getValue(); + if (L->getUniqueExitBlock()) { + SmallVector DbgUsers; + findDbgUsers(DbgUsers, IndVar); + L->preserveDebugInductionVariableInfo(FinalIVValue, DbgUsers); + } + } + } + } + // The insertion point instruction may have been deleted; clear it out // so that the rewriter doesn't trip over it later. Rewriter.clearInsertPoint(); diff --git a/llvm/test/Transforms/IndVarSimplify/pr51735-1.ll b/llvm/test/Transforms/IndVarSimplify/pr51735-1.ll new file mode 100644 index 000000000000..356217985fed --- /dev/null +++ b/llvm/test/Transforms/IndVarSimplify/pr51735-1.ll @@ -0,0 +1,129 @@ +; RUN: opt -passes="loop(indvars)" \ +; RUN: --experimental-debuginfo-iterators=false -S -o - < %s | \ +; RUN: FileCheck --check-prefix=CHECK %s +; RUN: opt -passes="loop(indvars,loop-deletion)" \ +; RUN: --experimental-debuginfo-iterators=false -S -o - < %s | \ +; RUN: FileCheck --check-prefix=CHECK %s + +; Make sure that when we delete the loop, that the variable Index has +; the 777 value. + +; As this test case does fire the 'indvars' transformation, the debug values +; are added to the 'for.end' exit block. No debug values are preserved by the +; pass to be used by the 'loop-deletion' pass. + +; CHECK: for.cond: +; CHECK: call void @llvm.dbg.value(metadata i32 %[[SSA_INDEX_0:.+]], metadata ![[DBG:[0-9]+]], {{.*}} + +; CHECK: for.extra: +; CHECK: %[[SSA_CALL_0:.+]] = call noundef i32 @"?nop@@YAHH@Z"(i32 noundef %[[SSA_INDEX_0]]), {{.*}} +; CHECK: br i1 %[[SSA_CMP_0:.+]], label %for.cond, label %if.else, {{.*}} + +; CHECK: if.then: +; CHECK: call void @llvm.dbg.value(metadata i32 777, metadata ![[DBG]], {{.*}} +; CHECK: call void @llvm.dbg.value(metadata i32 %[[SSA_VAR_1:.+]], metadata ![[VAR:[0-9]+]], {{.*}} +; CHECK: br label %for.end, {{.*}} + +; CHECK: if.else: +; CHECK: call void @llvm.dbg.value(metadata i32 %[[SSA_VAR_2:.+]], metadata ![[VAR:[0-9]+]], {{.*}} +; CHECK: br label %for.end, {{.*}} + +; CHECK: for.end: +; CHECK: call void @llvm.dbg.value(metadata i32 777, metadata ![[DBG]], {{.*}} + +; CHECK-DAG: ![[DBG]] = !DILocalVariable(name: "Index"{{.*}}) +; CHECK-DAG: ![[VAR]] = !DILocalVariable(name: "Var"{{.*}}) + +define dso_local noundef i32 @"?nop@@YAHH@Z"(i32 noundef %Param) !dbg !11 { +entry: + %Param.addr = alloca i32, align 4 + store i32 %Param, ptr %Param.addr, align 4 + call void @llvm.dbg.declare(metadata ptr %Param.addr, metadata !32, metadata !DIExpression()), !dbg !35 + ret i32 0, !dbg !36 +} + +define dso_local void @_Z3barv() local_unnamed_addr #1 !dbg !12 { +entry: + call void @llvm.dbg.value(metadata i32 777, metadata !16, metadata !DIExpression()), !dbg !17 + call void @llvm.dbg.value(metadata i32 27, metadata !18, metadata !DIExpression()), !dbg !17 + call void @llvm.dbg.value(metadata i32 1, metadata !19, metadata !DIExpression()), !dbg !17 + call void @llvm.dbg.value(metadata i32 1, metadata !30, metadata !DIExpression()), !dbg !17 + br label %for.cond, !dbg !20 + +for.cond: ; preds = %for.cond, %entry + %Index.0 = phi i32 [ 27, %entry ], [ %inc, %for.extra ], !dbg !17 + call void @llvm.dbg.value(metadata i32 %Index.0, metadata !18, metadata !DIExpression()), !dbg !17 + %cmp = icmp ult i32 %Index.0, 777, !dbg !21 + %inc = add nuw nsw i32 %Index.0, 1, !dbg !24 + call void @llvm.dbg.value(metadata i32 %inc, metadata !18, metadata !DIExpression()), !dbg !17 + br i1 %cmp, label %for.extra, label %if.then, !dbg !25, !llvm.loop !26 + +for.extra: + %call.0 = call noundef i32 @"?nop@@YAHH@Z"(i32 noundef %Index.0), !dbg !21 + %cmp.0 = icmp ult i32 %Index.0, %call.0, !dbg !21 + br i1 %cmp.0, label %for.cond, label %if.else, !dbg !25, !llvm.loop !26 + +if.then: ; preds = %for.cond + %Var.1 = add nsw i32 %Index.0, 1, !dbg !20 + call void @llvm.dbg.value(metadata i32 %Var.1, metadata !19, metadata !DIExpression()), !dbg !20 + br label %for.end, !dbg !20 + +if.else: + %Var.2 = add nsw i32 %Index.0, 2, !dbg !20 + call void @llvm.dbg.value(metadata i32 %Var.2, metadata !19, metadata !DIExpression()), !dbg !20 + br label %for.end, !dbg !20 + +for.end: ; preds = %if.else, %if.then + %Zeta.0 = phi i32 [ %Var.1, %if.then ], [ %Var.2, %if.else ], !dbg !20 + call void @llvm.dbg.value(metadata i32 %Zeta.0, metadata !30, metadata !DIExpression()), !dbg !20 + %Var.3 = add nsw i32 %Index.0, 1, !dbg !20 + call void @llvm.dbg.value(metadata i32 %Var.3, metadata !19, metadata !DIExpression()), !dbg !20 + %call = call noundef i32 @"?nop@@YAHH@Z"(i32 noundef %Index.0), !dbg !37 + ret void, !dbg !29 +} + +declare void @llvm.dbg.value(metadata, metadata, metadata) +declare void @llvm.dbg.declare(metadata, metadata, metadata) + +!llvm.dbg.cu = !{!0} +!llvm.module.flags = !{!2, !3, !4, !5, !6, !7, !8} +!llvm.ident = !{!9} + +!0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus_14, file: !1, producer: "clang", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, splitDebugInlining: false, nameTableKind: None) +!1 = !DIFile(filename: "test.cpp", directory: "") +!2 = !{i32 7, !"Dwarf Version", i32 5} +!3 = !{i32 2, !"Debug Info Version", i32 3} +!4 = !{i32 1, !"wchar_size", i32 4} +!5 = !{i32 8, !"PIC Level", i32 2} +!6 = !{i32 7, !"PIE Level", i32 2} +!7 = !{i32 7, !"uwtable", i32 2} +!8 = !{i32 7, !"frame-pointer", i32 2} +!9 = !{!"clang version 18.0.0"} +!10 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) +!11 = distinct !DISubprogram(name: "nop", linkageName: "?nop@@YAHH@Z", scope: !1, file: !1, line: 1, type: !33, scopeLine: 1, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !31) +!12 = distinct !DISubprogram(name: "bar", linkageName: "_Z3barv", scope: !1, file: !1, line: 5, type: !13, scopeLine: 5, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !0, retainedNodes: !15) +!13 = !DISubroutineType(types: !14) +!14 = !{null} +!15 = !{} +!16 = !DILocalVariable(name: "End", scope: !12, file: !1, line: 6, type: !10) +!17 = !DILocation(line: 0, scope: !12) +!18 = !DILocalVariable(name: "Index", scope: !12, file: !1, line: 7, type: !10) +!19 = !DILocalVariable(name: "Var", scope: !12, file: !1, line: 8, type: !10) +!20 = !DILocation(line: 9, column: 3, scope: !12) +!21 = !DILocation(line: 9, column: 16, scope: !22) +!22 = distinct !DILexicalBlock(scope: !23, file: !1, line: 9, column: 3) +!23 = distinct !DILexicalBlock(scope: !12, file: !1, line: 9, column: 3) +!24 = !DILocation(line: 9, column: 23, scope: !22) +!25 = !DILocation(line: 9, column: 3, scope: !23) +!26 = distinct !{!26, !25, !27, !28} +!27 = !DILocation(line: 10, column: 5, scope: !23) +!28 = !{!"llvm.loop.mustprogress"} +!29 = !DILocation(line: 12, column: 1, scope: !12) +!30 = !DILocalVariable(name: "Zeta", scope: !12, file: !1, line: 8, type: !10) +!31 = !{!32} +!32 = !DILocalVariable(name: "Param", arg: 1, scope: !11, file: !1, line: 1, type: !10) +!33 = !DISubroutineType(types: !34) +!34 = !{!10, !10} +!35 = !DILocation(line: 1, scope: !11) +!36 = !DILocation(line: 2, scope: !11) +!37 = !DILocation(line: 20, scope: !12) diff --git a/llvm/test/Transforms/IndVarSimplify/pr51735-2.ll b/llvm/test/Transforms/IndVarSimplify/pr51735-2.ll new file mode 100644 index 000000000000..58cc9932e04c --- /dev/null +++ b/llvm/test/Transforms/IndVarSimplify/pr51735-2.ll @@ -0,0 +1,128 @@ +; RUN: opt -passes="loop(indvars)" \ +; RUN: --experimental-debuginfo-iterators=false -S -o - < %s | \ +; RUN: FileCheck --implicit-check-not="call void @llvm.dbg" \ +; RUN: --check-prefix=ALL-CHECK --check-prefix=PRE-CHECK %s +; RUN: opt -passes="loop(indvars,loop-deletion)" \ +; RUN: --experimental-debuginfo-iterators=false -S -o - < %s | \ +; RUN: FileCheck --implicit-check-not="call void @llvm.dbg" \ +; RUN: --check-prefix=ALL-CHECK --check-prefix=POST-CHECK %s + +; Check what happens to a modified but otherwise unused variable in a loop +; that gets deleted. The assignment in the loop is 'forgotten' by LLVM and +; doesn't appear in the debugging information. This behaviour is suboptimal, +; but we want to know if it changes + +; For all cases, LLDB shows +; Var = + +; 1 __attribute__((optnone)) int nop() { +; 2 return 0; +; 3 } +; 4 +; 5 void bar() { +; 6 int End = 777; +; 7 int Index = 27; +; 8 char Var = 1; +; 9 for (; Index < End; ++Index) { +; 10 if (Index == 666) { +; 11 ++Var; +; 12 } +; 13 } +; 14 nop(); +; 15 } + +; ALL-CHECK: entry: +; ALL-CHECK: call void @llvm.dbg.value(metadata i32 1, metadata ![[DBG:[0-9]+]], {{.*}} + +; Only the 'indvars' pass is executed. +; PRE-CHECK: for.cond: +; PRE-CHECK: call void @llvm.dbg.value(metadata i32 %[[SSA_VAR_0:.+]], metadata ![[DBG]], {{.*}} +; PRE-CHECK: call void @llvm.dbg.value(metadata !DIArgList{{.*}} + +; PRE-CHECK: for.body: +; PRE-CHECK: {{.*}} = icmp eq i32 %[[SSA_INDEX_0:.+]], 666 +; PRE-CHECK: {{.*}} = add nsw i32 %[[SSA_VAR_0]], 1 +; PRE-CHECK: {{.*}} = select i1 {{.*}}, i32 {{.*}}, i32 %[[SSA_VAR_0]] +; PRE-CHECK: call void @llvm.dbg.value(metadata i32 {{.*}}, metadata ![[DBG]], {{.*}} +; PRE-CHECK: br label %for.cond + +; PRE-CHECK: for.end: +; PRE-CHECK: ret void +; PRE-CHECK-DAG: ![[DBG]] = !DILocalVariable(name: "Var"{{.*}}) + +; The 'indvars' and 'loop-deletion' passes are executed. +; POST-CHECK: for.end: +; POST-CHECK: call void @llvm.dbg.value(metadata i32 undef, metadata ![[DBG:[0-9]+]], {{.*}} +; POST-CHECK: ret void +; POST-CHECK-DAG: ![[DBG]] = !DILocalVariable(name: "Var"{{.*}}) + +define dso_local void @_Z3barv() local_unnamed_addr !dbg !18 { +entry: + call void @llvm.dbg.value(metadata i32 1, metadata !24, metadata !DIExpression()), !dbg !22 + br label %for.cond, !dbg !25 + +for.cond: ; preds = %for.cond, %entry + %Index.0 = phi i32 [ 27, %entry ], [ %inc2, %for.body ], !dbg !22 + %Var.0 = phi i32 [ 1, %entry ], [ %spec.select, %for.body ], !dbg !22 + call void @llvm.dbg.value(metadata i32 %Var.0, metadata !24, metadata !DIExpression()), !dbg !22 + %cmp = icmp ult i32 %Index.0, 777, !dbg !26 + call void @llvm.dbg.value(metadata !DIArgList(i32 poison, i32 %Index.0), metadata !24, metadata !DIExpression(DW_OP_LLVM_arg, 0, DW_OP_LLVM_arg, 1, DW_OP_constu, 666, DW_OP_eq, DW_OP_LLVM_convert, 1, DW_ATE_unsigned, DW_OP_LLVM_convert, 32, DW_ATE_unsigned, DW_OP_plus, DW_OP_stack_value)), !dbg !22 + %inc2 = add nuw nsw i32 %Index.0, 1, !dbg !29 + br i1 %cmp, label %for.body, label %for.end, !dbg !30, !llvm.loop !31 + +for.body: ; preds = %for.cond + %cmp1 = icmp eq i32 %Index.0, 666, !dbg !30 + %inc = add nsw i32 %Var.0, 1 + %spec.select = select i1 %cmp1, i32 %inc, i32 %Var.0, !dbg !32 + call void @llvm.dbg.value(metadata i32 %spec.select, metadata !24, metadata !DIExpression()), !dbg !22 + br label %for.cond, !dbg !34, !llvm.loop !35 + +for.end: ; preds = %for.cond + ret void, !dbg !35 +} + +declare void @llvm.dbg.value(metadata, metadata, metadata) + +!llvm.dbg.cu = !{!0} +!llvm.module.flags = !{!2, !3, !4, !5, !6, !7, !8} +!llvm.ident = !{!9} + +!0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus_14, file: !1, producer: "clang", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, splitDebugInlining: false, nameTableKind: None) +!1 = !DIFile(filename: "test-b.cpp", directory: "") +!2 = !{i32 7, !"Dwarf Version", i32 5} +!3 = !{i32 2, !"Debug Info Version", i32 3} +!4 = !{i32 1, !"wchar_size", i32 4} +!5 = !{i32 8, !"PIC Level", i32 2} +!6 = !{i32 7, !"PIE Level", i32 2} +!7 = !{i32 7, !"uwtable", i32 2} +!8 = !{i32 7, !"frame-pointer", i32 2} +!9 = !{!"clang version 19.0.0"} +!10 = distinct !DISubprogram(name: "nop", linkageName: "_Z3nopi", scope: !1, file: !1, line: 1, type: !11, scopeLine: 1, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !0, retainedNodes: !14) +!11 = !DISubroutineType(types: !12) +!12 = !{!13, !13} +!13 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) +!14 = !{} +!15 = !DILocalVariable(name: "Param", arg: 1, scope: !10, file: !1, line: 1, type: !13) +!16 = !DILocation(line: 1, column: 38, scope: !10) +!17 = !DILocation(line: 2, column: 3, scope: !10) +!18 = distinct !DISubprogram(name: "bar", linkageName: "_Z3barv", scope: !1, file: !1, line: 5, type: !19, scopeLine: 5, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !0, retainedNodes: !14) +!19 = !DISubroutineType(types: !20) +!20 = !{null} +!22 = !DILocation(line: 0, scope: !18) +!24 = !DILocalVariable(name: "Var", scope: !18, file: !1, line: 8, type: !13) +!25 = !DILocation(line: 9, column: 3, scope: !18) +!26 = !DILocation(line: 9, column: 16, scope: !27) +!27 = distinct !DILexicalBlock(scope: !28, file: !1, line: 9, column: 3) +!28 = distinct !DILexicalBlock(scope: !18, file: !1, line: 9, column: 3) +!29 = !DILocation(line: 9, column: 23, scope: !27) +!30 = !DILocation(line: 9, column: 3, scope: !28) +!31 = distinct !{!31, !30, !32, !33} +!32 = !DILocation(line: 11, column: 9, scope: !28) +!33 = !{!"llvm.loop.mustprogress"} +!34 = !DILocation(line: 12, column: 3, scope: !18) +!35 = !DILocation(line: 13, column: 1, scope: !18) +!36 = distinct !DISubprogram(name: "main", scope: !1, file: !1, line: 15, type: !37, scopeLine: 15, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !0) +!37 = !DISubroutineType(types: !38) +!38 = !{!13} +!39 = !DILocation(line: 16, column: 3, scope: !36) +!40 = !DILocation(line: 17, column: 1, scope: !36) diff --git a/llvm/test/Transforms/IndVarSimplify/pr51735-3.ll b/llvm/test/Transforms/IndVarSimplify/pr51735-3.ll new file mode 100644 index 000000000000..ac9964743e0f --- /dev/null +++ b/llvm/test/Transforms/IndVarSimplify/pr51735-3.ll @@ -0,0 +1,131 @@ +; RUN: opt -passes="loop(indvars)" \ +; RUN: --experimental-debuginfo-iterators=false -S -o - < %s | \ +; RUN: FileCheck --implicit-check-not="call void @llvm.dbg" \ +; RUN: --check-prefix=ALL-CHECK --check-prefix=PRE-CHECK %s +; RUN: opt -passes="loop(indvars,loop-deletion)" \ +; RUN: --experimental-debuginfo-iterators=false -S -o - < %s | \ +; RUN: FileCheck --implicit-check-not="call void @llvm.dbg" \ +; RUN: --check-prefix=ALL-CHECK --check-prefix=POST-CHECK %s + +; Check what happens to a modified but otherwise unused variable in a loop +; that gets deleted. The assignment in the loop is 'forgotten' by LLVM and +; doesn't appear in the debugging information. This behaviour is suboptimal, +; but we want to know if it changes + +; For all cases, LLDB shows +; Var = + +; 1 __attribute__((optnone)) int nop() { +; 2 return 0; +; 3 } +; 4 +; 5 void bar() { +; 6 int End = 777; +; 7 int Index = 27; +; 8 char Var = 1; +; 9 for (; Index < End; ++Index) { +; 10 if (Index == 666) { +; 11 Var = 555; +; 12 } +; 13 } +; 14 nop(); +; 15 } + +; ALL-CHECK: entry: +; ALL-CHECK: call void @llvm.dbg.value(metadata i32 1, metadata ![[DBG:[0-9]+]], {{.*}} + +; Only the 'indvars' pass is executed. +; PRE-CHECK: if.then: +; PRE-CHECK: call void @llvm.dbg.value(metadata i32 555, metadata ![[DBG]], {{.*}} + +; PRE-CHECK: for.inc: +; PRE-CHECK: %[[SSA_VAR_0:.+]] = phi i32 [ 1, %for.body ], [ 555, %if.then ] +; PRE-CHECK: call void @llvm.dbg.value(metadata i32 %[[SSA_VAR_0]], metadata ![[DBG]], {{.*}} +; PRE-CHECK: {{.*}} = add nuw nsw i32 %[[SSA_INDEX_0:.+]], 1 +; PRE-CHECK: br label %for.cond + +; PRE-CHECK: for.end: +; PRE-CHECK: ret void +; PRE-CHECK-DAG: ![[DBG]] = !DILocalVariable(name: "Var"{{.*}}) + +; The 'indvars' and 'loop-deletion' passes are executed. +; POST-CHECK: for.end: +; POST-CHECK: call void @llvm.dbg.value(metadata i32 555, metadata ![[DBG]], {{.*}} +; POST-CHECK: ret void +; POST-CHECK-DAG: ![[DBG]] = !DILocalVariable(name: "Var"{{.*}}) + +define dso_local void @_Z3barv() local_unnamed_addr !dbg !18 { +entry: + call void @llvm.dbg.value(metadata i32 1, metadata !24, metadata !DIExpression()), !dbg !22 + br label %for.cond, !dbg !25 + +for.cond: ; preds = %for.inc, %entry + %Index.0 = phi i32 [ 27, %entry ], [ %inc, %for.inc ], !dbg !22 + %cmp = icmp ult i32 %Index.0, 777, !dbg !26 + br i1 %cmp, label %for.body, label %for.end, !dbg !30, !llvm.loop !29 + +for.body: ; preds = %for.cond + %cmp1 = icmp eq i32 %Index.0, 666, !dbg !30 + br i1 %cmp1, label %if.then, label %for.inc, !dbg !32 + +if.then: ; preds = %for.body + call void @llvm.dbg.value(metadata i32 555, metadata !24, metadata !DIExpression()), !dbg !22 + br label %for.inc, !dbg !34, !llvm.loop !32 + +for.inc: ; preds = %for.body, %if.then + %Var.0 = phi i32 [ 1, %for.body ], [ 555, %if.then ], !dbg !22 + call void @llvm.dbg.value(metadata i32 %Var.0, metadata !24, metadata !DIExpression()), !dbg !22 + %inc = add nuw nsw i32 %Index.0, 1, !dbg !29 + br label %for.cond, !dbg !34, !llvm.loop !35 + +for.end: ; preds = %for.cond + ret void, !dbg !35 +} + +declare void @llvm.dbg.value(metadata, metadata, metadata) + +!llvm.dbg.cu = !{!0} +!llvm.module.flags = !{!2, !3, !4, !5, !6, !7, !8} +!llvm.ident = !{!9} + +!0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus_14, file: !1, producer: "clang", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, splitDebugInlining: false, nameTableKind: None) +!1 = !DIFile(filename: "test-c.cpp", directory: "") +!2 = !{i32 7, !"Dwarf Version", i32 5} +!3 = !{i32 2, !"Debug Info Version", i32 3} +!4 = !{i32 1, !"wchar_size", i32 4} +!5 = !{i32 8, !"PIC Level", i32 2} +!6 = !{i32 7, !"PIE Level", i32 2} +!7 = !{i32 7, !"uwtable", i32 2} +!8 = !{i32 7, !"frame-pointer", i32 2} +!9 = !{!"clang version 19.0.0"} +!10 = distinct !DISubprogram(name: "nop", linkageName: "_Z3nopi", scope: !1, file: !1, line: 1, type: !11, scopeLine: 1, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !0, retainedNodes: !14) +!11 = !DISubroutineType(types: !12) +!12 = !{!13, !13} +!13 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) +!14 = !{} +!15 = !DILocalVariable(name: "Param", arg: 1, scope: !10, file: !1, line: 1, type: !13) +!16 = !DILocation(line: 1, column: 38, scope: !10) +!17 = !DILocation(line: 2, column: 3, scope: !10) +!18 = distinct !DISubprogram(name: "bar", linkageName: "_Z3barv", scope: !1, file: !1, line: 5, type: !19, scopeLine: 5, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !0, retainedNodes: !14) +!19 = !DISubroutineType(types: !20) +!20 = !{null} +!21 = !DILocalVariable(name: "End", scope: !18, file: !1, line: 6, type: !13) +!22 = !DILocation(line: 0, scope: !18) +!23 = !DILocalVariable(name: "Index", scope: !18, file: !1, line: 7, type: !13) +!24 = !DILocalVariable(name: "Var", scope: !18, file: !1, line: 8, type: !13) +!25 = !DILocation(line: 9, column: 3, scope: !18) +!26 = !DILocation(line: 9, column: 16, scope: !27) +!27 = distinct !DILexicalBlock(scope: !28, file: !1, line: 9, column: 3) +!28 = distinct !DILexicalBlock(scope: !18, file: !1, line: 9, column: 3) +!29 = !DILocation(line: 9, column: 23, scope: !27) +!30 = !DILocation(line: 9, column: 3, scope: !28) +!31 = distinct !{!31, !30, !32, !33} +!32 = !DILocation(line: 11, column: 13, scope: !28) +!33 = !{!"llvm.loop.mustprogress"} +!34 = !DILocation(line: 12, column: 3, scope: !18) +!35 = !DILocation(line: 13, column: 1, scope: !18) +!36 = distinct !DISubprogram(name: "main", scope: !1, file: !1, line: 15, type: !37, scopeLine: 15, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !0) +!37 = !DISubroutineType(types: !38) +!38 = !{!13} +!39 = !DILocation(line: 16, column: 3, scope: !36) +!40 = !DILocation(line: 17, column: 1, scope: !36) diff --git a/llvm/test/Transforms/IndVarSimplify/pr51735.ll b/llvm/test/Transforms/IndVarSimplify/pr51735.ll new file mode 100644 index 000000000000..3014b3467852 --- /dev/null +++ b/llvm/test/Transforms/IndVarSimplify/pr51735.ll @@ -0,0 +1,104 @@ +; RUN: opt -passes="loop(indvars)" \ +; RUN: --experimental-debuginfo-iterators=false -S -o - < %s | \ +; RUN: FileCheck --check-prefix=PRE-CHECK %s +; RUN: opt -passes="loop(indvars,loop-deletion)" \ +; RUN: --experimental-debuginfo-iterators=false -S -o - < %s | \ +; RUN: FileCheck --check-prefix=POST-CHECK %s + +; Make sure that when we delete the loop in the code below, that the variable +; Index has the 777 value. + +; 1 __attribute__((optnone)) int nop() { +; 2 return 0; +; 3 } +; 4 +; 5 void bar() { +; 6 int End = 777; +; 7 int Index = 27; +; 8 char Var = 1; +; 9 for (; Index < End; ++Index) +; 10 ; +; 11 nop(); +; 12 } +; 13 +; 14 int main () { +; 15 bar(); +; 16 } + +; Only the 'indvars' pass is executed. +; As this test case does not fire the 'indvars' transformation, no debug values +; are preserved and or added. + +; PRE-CHECK: for.cond: +; PRE-CHECK: call void @llvm.dbg.value(metadata i32 poison, metadata ![[DBG_1:[0-9]+]], {{.*}} +; PRE-CHECK: call void @llvm.dbg.value(metadata i32 poison, metadata ![[DBG_1]], {{.*}} +; PRE-CHECK: br i1 false, label %for.cond, label %for.end + +; PRE-CHECK: for.end: +; PRE-CHECK-NOT: call void @llvm.dbg.value +; PRE-CHECK: ret void +; PRE-CHECK-DAG: ![[DBG_1]] = !DILocalVariable(name: "Index"{{.*}}) + +; The 'indvars' and 'loop-deletion' passes are executed. +; The loop is deleted and the debug values collected by 'indvars' are used by +; 'loop-deletion' to add the induction variable debug value. + +; POST-CHECK: for.end: +; POST-CHECK: call void @llvm.dbg.value(metadata i32 777, metadata ![[DBG_2:[0-9]+]], {{.*}} +; POST-CHECK: ret void +; POST-CHECK-DAG: ![[DBG_2]] = !DILocalVariable(name: "Index"{{.*}}) + +define dso_local void @_Z3barv() local_unnamed_addr #1 !dbg !15 { +entry: + call void @llvm.dbg.value(metadata i32 777, metadata !19, metadata !DIExpression()), !dbg !20 + call void @llvm.dbg.value(metadata i32 27, metadata !21, metadata !DIExpression()), !dbg !20 + call void @llvm.dbg.value(metadata i32 1, metadata !22, metadata !DIExpression()), !dbg !20 + br label %for.cond, !dbg !23 + +for.cond: ; preds = %for.cond, %entry + %Index.0 = phi i32 [ 27, %entry ], [ %inc, %for.cond ], !dbg !20 + call void @llvm.dbg.value(metadata i32 %Index.0, metadata !21, metadata !DIExpression()), !dbg !20 + %cmp = icmp ult i32 %Index.0, 777, !dbg !24 + %inc = add nuw nsw i32 %Index.0, 1, !dbg !27 + call void @llvm.dbg.value(metadata i32 %inc, metadata !21, metadata !DIExpression()), !dbg !20 + br i1 %cmp, label %for.cond, label %for.end, !dbg !28, !llvm.loop !29 + +for.end: ; preds = %for.cond + ret void, !dbg !33 +} + +declare void @llvm.dbg.value(metadata, metadata, metadata) + +!llvm.dbg.cu = !{!0} +!llvm.module.flags = !{!2, !3, !4, !5, !6, !7, !8} +!llvm.ident = !{!9} + +!0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus_14, file: !1, producer: "clang", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, splitDebugInlining: false, nameTableKind: None) +!1 = !DIFile(filename: "test.cpp", directory: "") +!2 = !{i32 7, !"Dwarf Version", i32 5} +!3 = !{i32 2, !"Debug Info Version", i32 3} +!4 = !{i32 1, !"wchar_size", i32 4} +!5 = !{i32 8, !"PIC Level", i32 2} +!6 = !{i32 7, !"PIE Level", i32 2} +!7 = !{i32 7, !"uwtable", i32 2} +!8 = !{i32 7, !"frame-pointer", i32 2} +!9 = !{!"clang version 18.0.0"} +!13 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) +!15 = distinct !DISubprogram(name: "bar", linkageName: "_Z3barv", scope: !1, file: !1, line: 5, type: !16, scopeLine: 5, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !0, retainedNodes: !18) +!16 = !DISubroutineType(types: !17) +!17 = !{null} +!18 = !{} +!19 = !DILocalVariable(name: "End", scope: !15, file: !1, line: 6, type: !13) +!20 = !DILocation(line: 0, scope: !15) +!21 = !DILocalVariable(name: "Index", scope: !15, file: !1, line: 7, type: !13) +!22 = !DILocalVariable(name: "Var", scope: !15, file: !1, line: 8, type: !13) +!23 = !DILocation(line: 9, column: 3, scope: !15) +!24 = !DILocation(line: 9, column: 16, scope: !25) +!25 = distinct !DILexicalBlock(scope: !26, file: !1, line: 9, column: 3) +!26 = distinct !DILexicalBlock(scope: !15, file: !1, line: 9, column: 3) +!27 = !DILocation(line: 9, column: 23, scope: !25) +!28 = !DILocation(line: 9, column: 3, scope: !26) +!29 = distinct !{!29, !28, !30, !31} +!30 = !DILocation(line: 10, column: 5, scope: !26) +!31 = !{!"llvm.loop.mustprogress"} +!33 = !DILocation(line: 12, column: 1, scope: !15) -- GitLab From c769079b1098f6b108544176c0bd8b5bba986f2c Mon Sep 17 00:00:00 2001 From: AtariDreams Date: Wed, 22 May 2024 02:10:14 -0400 Subject: [PATCH 073/452] [AMDGPU] Update test results to fix build (#92982) --- llvm/test/CodeGen/AMDGPU/fp_to_sint.ll | 395 +++--- llvm/test/CodeGen/AMDGPU/fp_to_uint.ll | 395 +++--- llvm/test/CodeGen/AMDGPU/llvm.exp.ll | 1592 ++++++++++++------------ llvm/test/CodeGen/AMDGPU/llvm.exp10.ll | 1592 ++++++++++++------------ llvm/test/CodeGen/AMDGPU/shl.ll | 216 ++-- 5 files changed, 2077 insertions(+), 2113 deletions(-) diff --git a/llvm/test/CodeGen/AMDGPU/fp_to_sint.ll b/llvm/test/CodeGen/AMDGPU/fp_to_sint.ll index 64063f65e288..04ef30bd26aa 100644 --- a/llvm/test/CodeGen/AMDGPU/fp_to_sint.ll +++ b/llvm/test/CodeGen/AMDGPU/fp_to_sint.ll @@ -253,25 +253,25 @@ define amdgpu_kernel void @fp_to_sint_i64 (ptr addrspace(1) %out, float %in) { ; EG-NEXT: ADD_INT * T2.W, PV.W, literal.y, ; EG-NEXT: 8388608(1.175494e-38), -150(nan) ; EG-NEXT: ADD_INT T0.X, T0.W, literal.x, -; EG-NEXT: SUB_INT T0.Y, literal.y, T0.W, -; EG-NEXT: AND_INT T0.Z, PS, literal.z, +; EG-NEXT: AND_INT T0.Y, PS, literal.y, +; EG-NEXT: SUB_INT T0.Z, literal.z, T0.W, ; EG-NEXT: NOT_INT T0.W, PS, ; EG-NEXT: LSHR * T3.W, PV.W, 1, -; EG-NEXT: -127(nan), 150(2.101948e-43) -; EG-NEXT: 31(4.344025e-44), 0(0.000000e+00) +; EG-NEXT: -127(nan), 31(4.344025e-44) +; EG-NEXT: 150(2.101948e-43), 0(0.000000e+00) ; EG-NEXT: BIT_ALIGN_INT T1.X, 0.0, PS, PV.W, -; EG-NEXT: LSHL T1.Y, T1.W, PV.Z, -; EG-NEXT: AND_INT T0.Z, T2.W, literal.x, BS:VEC_120/SCL_212 -; EG-NEXT: BIT_ALIGN_INT T0.W, 0.0, T1.W, PV.Y, BS:VEC_021/SCL_122 -; EG-NEXT: AND_INT * T1.W, PV.Y, literal.x, +; EG-NEXT: AND_INT T1.Y, PV.Z, literal.x, +; EG-NEXT: BIT_ALIGN_INT T0.Z, 0.0, T1.W, PV.Z, +; EG-NEXT: LSHL T0.W, T1.W, PV.Y, +; EG-NEXT: AND_INT * T1.W, T2.W, literal.x, ; EG-NEXT: 32(4.484155e-44), 0(0.000000e+00) ; EG-NEXT: CNDE_INT T0.Y, PS, PV.W, 0.0, -; EG-NEXT: CNDE_INT T1.Z, PV.Z, PV.Y, 0.0, -; EG-NEXT: CNDE_INT T0.W, PV.Z, PV.X, PV.Y, +; EG-NEXT: CNDE_INT T0.Z, PV.Y, PV.Z, 0.0, +; EG-NEXT: CNDE_INT T0.W, PS, PV.X, PV.W, ; EG-NEXT: SETGT_INT * T1.W, T0.X, literal.x, ; EG-NEXT: 23(3.222986e-44), 0(0.000000e+00) -; EG-NEXT: CNDE_INT T0.Z, PS, 0.0, PV.W, -; EG-NEXT: CNDE_INT T0.W, PS, PV.Y, PV.Z, +; EG-NEXT: CNDE_INT T1.Z, PS, 0.0, PV.W, +; EG-NEXT: CNDE_INT T0.W, PS, PV.Z, PV.Y, ; EG-NEXT: ASHR * T1.W, KC0[2].Z, literal.x, ; EG-NEXT: 31(4.344025e-44), 0(0.000000e+00) ; EG-NEXT: XOR_INT T0.W, PV.W, PS, @@ -364,79 +364,78 @@ define amdgpu_kernel void @fp_to_sint_v2i64(ptr addrspace(1) %out, <2 x float> % ; ; EG-LABEL: fp_to_sint_v2i64: ; EG: ; %bb.0: -; EG-NEXT: ALU 75, @4, KC0[CB0:0-32], KC1[] +; EG-NEXT: ALU 74, @4, KC0[CB0:0-32], KC1[] ; EG-NEXT: MEM_RAT_CACHELESS STORE_RAW T1.XYZW, T0.X, 1 ; EG-NEXT: CF_END ; EG-NEXT: PAD ; EG-NEXT: ALU clause starting at 4: ; EG-NEXT: MOV * T0.W, literal.x, ; EG-NEXT: 8(1.121039e-44), 0(0.000000e+00) -; EG-NEXT: BFE_UINT * T1.W, KC0[2].W, literal.x, PV.W, -; EG-NEXT: 23(3.222986e-44), 0(0.000000e+00) -; EG-NEXT: AND_INT T0.Z, KC0[2].W, literal.x, -; EG-NEXT: BFE_UINT T0.W, KC0[3].X, literal.y, T0.W, -; EG-NEXT: ADD_INT * T2.W, PV.W, literal.z, -; EG-NEXT: 8388607(1.175494e-38), 23(3.222986e-44) +; EG-NEXT: BFE_UINT T0.Z, KC0[3].X, literal.x, PV.W, +; EG-NEXT: BFE_UINT T0.W, KC0[2].W, literal.x, PV.W, +; EG-NEXT: AND_INT * T1.Z, KC0[2].W, literal.y, +; EG-NEXT: 23(3.222986e-44), 8388607(1.175494e-38) +; EG-NEXT: ADD_INT T1.W, PV.W, literal.x, +; EG-NEXT: ADD_INT * T2.W, PV.Z, literal.x, ; EG-NEXT: -150(nan), 0(0.000000e+00) -; EG-NEXT: SUB_INT T0.X, literal.x, PV.W, -; EG-NEXT: SUB_INT T0.Y, literal.x, T1.W, -; EG-NEXT: AND_INT T1.Z, PS, literal.y, -; EG-NEXT: OR_INT T3.W, PV.Z, literal.z, +; EG-NEXT: AND_INT T0.X, PS, literal.x, +; EG-NEXT: AND_INT T0.Y, PV.W, literal.x, +; EG-NEXT: OR_INT T1.Z, T1.Z, literal.y, +; EG-NEXT: SUB_INT T3.W, literal.z, T0.W, ; EG-NEXT: AND_INT * T4.W, KC0[3].X, literal.w, -; EG-NEXT: 150(2.101948e-43), 31(4.344025e-44) -; EG-NEXT: 8388608(1.175494e-38), 8388607(1.175494e-38) +; EG-NEXT: 31(4.344025e-44), 8388608(1.175494e-38) +; EG-NEXT: 150(2.101948e-43), 8388607(1.175494e-38) ; EG-NEXT: OR_INT T1.X, PS, literal.x, -; EG-NEXT: LSHL T1.Y, PV.W, PV.Z, -; EG-NEXT: AND_INT T0.Z, T2.W, literal.y, -; EG-NEXT: BIT_ALIGN_INT T4.W, 0.0, PV.W, PV.Y, -; EG-NEXT: AND_INT * T5.W, PV.Y, literal.y, +; EG-NEXT: AND_INT T1.Y, PV.W, literal.y, +; EG-NEXT: BIT_ALIGN_INT T2.Z, 0.0, PV.Z, PV.W, +; EG-NEXT: LSHL T3.W, PV.Z, PV.Y, +; EG-NEXT: AND_INT * T4.W, T1.W, literal.y, ; EG-NEXT: 8388608(1.175494e-38), 32(4.484155e-44) -; EG-NEXT: CNDE_INT T2.X, PS, PV.W, 0.0, -; EG-NEXT: CNDE_INT T0.Y, PV.Z, PV.Y, 0.0, -; EG-NEXT: ADD_INT T1.Z, T0.W, literal.x, -; EG-NEXT: BIT_ALIGN_INT T4.W, 0.0, PV.X, T0.X, -; EG-NEXT: AND_INT * T5.W, T0.X, literal.y, -; EG-NEXT: -150(nan), 32(4.484155e-44) +; EG-NEXT: CNDE_INT T0.Y, PS, PV.W, 0.0, +; EG-NEXT: CNDE_INT T2.Z, PV.Y, PV.Z, 0.0, +; EG-NEXT: LSHL T5.W, PV.X, T0.X, +; EG-NEXT: AND_INT * T6.W, T2.W, literal.x, +; EG-NEXT: 32(4.484155e-44), 0(0.000000e+00) ; EG-NEXT: CNDE_INT T0.X, PS, PV.W, 0.0, -; EG-NEXT: NOT_INT T2.Y, T2.W, -; EG-NEXT: AND_INT T2.Z, PV.Z, literal.x, -; EG-NEXT: NOT_INT T2.W, PV.Z, -; EG-NEXT: LSHR * T4.W, T1.X, 1, -; EG-NEXT: 31(4.344025e-44), 0(0.000000e+00) -; EG-NEXT: LSHR T3.X, T3.W, 1, -; EG-NEXT: ADD_INT T3.Y, T0.W, literal.x, BS:VEC_120/SCL_212 -; EG-NEXT: BIT_ALIGN_INT T3.Z, 0.0, PS, PV.W, -; EG-NEXT: LSHL T0.W, T1.X, PV.Z, -; EG-NEXT: AND_INT * T2.W, T1.Z, literal.y, +; EG-NEXT: NOT_INT T1.Y, T1.W, +; EG-NEXT: SUB_INT T3.Z, literal.x, T0.Z, +; EG-NEXT: NOT_INT T1.W, T2.W, BS:VEC_120/SCL_212 +; EG-NEXT: LSHR * T2.W, T1.X, 1, +; EG-NEXT: 150(2.101948e-43), 0(0.000000e+00) +; EG-NEXT: LSHR T2.X, T1.Z, 1, +; EG-NEXT: ADD_INT T2.Y, T0.Z, literal.x, BS:VEC_120/SCL_212 +; EG-NEXT: BIT_ALIGN_INT T0.Z, 0.0, PS, PV.W, +; EG-NEXT: BIT_ALIGN_INT T1.W, 0.0, T1.X, PV.Z, +; EG-NEXT: AND_INT * T2.W, PV.Z, literal.y, ; EG-NEXT: -127(nan), 32(4.484155e-44) ; EG-NEXT: CNDE_INT T1.X, PS, PV.W, 0.0, -; EG-NEXT: CNDE_INT T4.Y, PS, PV.Z, PV.W, -; EG-NEXT: SETGT_INT T1.Z, PV.Y, literal.x, -; EG-NEXT: BIT_ALIGN_INT T0.W, 0.0, PV.X, T2.Y, -; EG-NEXT: ADD_INT * T1.W, T1.W, literal.y, +; EG-NEXT: CNDE_INT T3.Y, T6.W, PV.Z, T5.W, BS:VEC_021/SCL_122 +; EG-NEXT: SETGT_INT T0.Z, PV.Y, literal.x, +; EG-NEXT: BIT_ALIGN_INT T1.W, 0.0, PV.X, T1.Y, +; EG-NEXT: ADD_INT * T0.W, T0.W, literal.y, ; EG-NEXT: 23(3.222986e-44), -127(nan) -; EG-NEXT: CNDE_INT T3.X, T0.Z, PV.W, T1.Y, +; EG-NEXT: CNDE_INT T2.X, T4.W, PV.W, T3.W, ; EG-NEXT: SETGT_INT T1.Y, PS, literal.x, -; EG-NEXT: CNDE_INT T0.Z, PV.Z, 0.0, PV.Y, -; EG-NEXT: CNDE_INT T0.W, PV.Z, T0.X, PV.X, +; EG-NEXT: CNDE_INT T1.Z, PV.Z, 0.0, PV.Y, +; EG-NEXT: CNDE_INT T1.W, PV.Z, PV.X, T0.X, ; EG-NEXT: ASHR * T2.W, KC0[3].X, literal.y, ; EG-NEXT: 23(3.222986e-44), 31(4.344025e-44) ; EG-NEXT: XOR_INT T0.X, PV.W, PS, -; EG-NEXT: XOR_INT T2.Y, PV.Z, PS, +; EG-NEXT: XOR_INT T3.Y, PV.Z, PS, ; EG-NEXT: CNDE_INT T0.Z, PV.Y, 0.0, PV.X, -; EG-NEXT: CNDE_INT T0.W, PV.Y, T2.X, T0.Y, +; EG-NEXT: CNDE_INT T1.W, PV.Y, T2.Z, T0.Y, ; EG-NEXT: ASHR * T3.W, KC0[2].W, literal.x, ; EG-NEXT: 31(4.344025e-44), 0(0.000000e+00) ; EG-NEXT: XOR_INT T0.Y, PV.W, PS, ; EG-NEXT: XOR_INT T0.Z, PV.Z, PS, -; EG-NEXT: SUB_INT T0.W, PV.Y, T2.W, +; EG-NEXT: SUB_INT T1.W, PV.Y, T2.W, ; EG-NEXT: SUBB_UINT * T4.W, PV.X, T2.W, ; EG-NEXT: SUB_INT T1.Y, PV.W, PS, -; EG-NEXT: SETGT_INT T1.Z, 0.0, T3.Y, -; EG-NEXT: SUB_INT T0.W, PV.Z, T3.W, +; EG-NEXT: SETGT_INT T1.Z, 0.0, T2.Y, +; EG-NEXT: SUB_INT T1.W, PV.Z, T3.W, ; EG-NEXT: SUBB_UINT * T4.W, PV.Y, T3.W, ; EG-NEXT: SUB_INT T0.Z, PV.W, PS, -; EG-NEXT: SETGT_INT T0.W, 0.0, T1.W, +; EG-NEXT: SETGT_INT T0.W, 0.0, T0.W, ; EG-NEXT: CNDE_INT * T1.W, PV.Z, PV.Y, 0.0, ; EG-NEXT: CNDE_INT T1.Y, PV.W, PV.Z, 0.0, ; EG-NEXT: SUB_INT * T2.W, T0.X, T2.W, @@ -567,170 +566,168 @@ define amdgpu_kernel void @fp_to_sint_v4i64(ptr addrspace(1) %out, <4 x float> % ; ; EG-LABEL: fp_to_sint_v4i64: ; EG: ; %bb.0: -; EG-NEXT: ALU 101, @6, KC0[CB0:0-32], KC1[] -; EG-NEXT: ALU 54, @108, KC0[CB0:0-32], KC1[] -; EG-NEXT: MEM_RAT_CACHELESS STORE_RAW T4.XYZW, T0.X, 0 -; EG-NEXT: MEM_RAT_CACHELESS STORE_RAW T6.XYZW, T2.X, 1 +; EG-NEXT: ALU 99, @6, KC0[CB0:0-32], KC1[] +; EG-NEXT: ALU 54, @106, KC0[CB0:0-32], KC1[] +; EG-NEXT: MEM_RAT_CACHELESS STORE_RAW T1.XYZW, T2.X, 0 +; EG-NEXT: MEM_RAT_CACHELESS STORE_RAW T6.XYZW, T0.X, 1 ; EG-NEXT: CF_END ; EG-NEXT: PAD ; EG-NEXT: ALU clause starting at 6: ; EG-NEXT: MOV * T0.W, literal.x, ; EG-NEXT: 8(1.121039e-44), 0(0.000000e+00) -; EG-NEXT: BFE_UINT T1.W, KC0[4].X, literal.x, PV.W, -; EG-NEXT: AND_INT * T2.W, KC0[4].X, literal.y, +; EG-NEXT: BFE_UINT T1.W, KC0[3].Z, literal.x, PV.W, +; EG-NEXT: AND_INT * T2.W, KC0[3].Z, literal.y, ; EG-NEXT: 23(3.222986e-44), 8388607(1.175494e-38) -; EG-NEXT: OR_INT T0.Z, PS, literal.x, -; EG-NEXT: BFE_UINT T2.W, KC0[3].Z, literal.y, T0.W, -; EG-NEXT: ADD_INT * T3.W, PV.W, literal.z, -; EG-NEXT: 8388608(1.175494e-38), 23(3.222986e-44) -; EG-NEXT: -150(nan), 0(0.000000e+00) -; EG-NEXT: ADD_INT T0.Y, PV.W, literal.x, -; EG-NEXT: AND_INT T1.Z, PS, literal.y, -; EG-NEXT: NOT_INT T4.W, PS, -; EG-NEXT: LSHR * T5.W, PV.Z, 1, -; EG-NEXT: -127(nan), 31(4.344025e-44) +; EG-NEXT: OR_INT T2.W, PS, literal.x, +; EG-NEXT: ADD_INT * T3.W, PV.W, literal.y, +; EG-NEXT: 8388608(1.175494e-38), -150(nan) ; EG-NEXT: ADD_INT T0.X, T1.W, literal.x, -; EG-NEXT: BIT_ALIGN_INT T1.Y, 0.0, PS, PV.W, -; EG-NEXT: AND_INT T2.Z, T3.W, literal.y, BS:VEC_201 -; EG-NEXT: LSHL T3.W, T0.Z, PV.Z, -; EG-NEXT: SUB_INT * T1.W, literal.z, T1.W, -; EG-NEXT: -127(nan), 32(4.484155e-44) -; EG-NEXT: 150(2.101948e-43), 0(0.000000e+00) -; EG-NEXT: AND_INT T1.X, PS, literal.x, -; EG-NEXT: BIT_ALIGN_INT T2.Y, 0.0, T0.Z, PS, -; EG-NEXT: AND_INT T0.Z, KC0[3].Z, literal.y, -; EG-NEXT: CNDE_INT T1.W, PV.Z, PV.Y, PV.W, -; EG-NEXT: SETGT_INT * T4.W, PV.X, literal.z, +; EG-NEXT: BFE_UINT T0.Y, KC0[4].X, literal.y, T0.W, +; EG-NEXT: AND_INT T0.Z, PS, literal.z, +; EG-NEXT: NOT_INT T4.W, PS, +; EG-NEXT: LSHR * T5.W, PV.W, 1, +; EG-NEXT: -127(nan), 23(3.222986e-44) +; EG-NEXT: 31(4.344025e-44), 0(0.000000e+00) +; EG-NEXT: BIT_ALIGN_INT T1.X, 0.0, PS, PV.W, +; EG-NEXT: AND_INT T1.Y, T3.W, literal.x, +; EG-NEXT: LSHL T0.Z, T2.W, PV.Z, BS:VEC_120/SCL_212 +; EG-NEXT: AND_INT T3.W, KC0[4].X, literal.y, +; EG-NEXT: ADD_INT * T4.W, PV.Y, literal.z, ; EG-NEXT: 32(4.484155e-44), 8388607(1.175494e-38) +; EG-NEXT: -150(nan), 0(0.000000e+00) +; EG-NEXT: AND_INT T2.Y, PS, literal.x, +; EG-NEXT: OR_INT T1.Z, PV.W, literal.y, +; EG-NEXT: CNDE_INT T3.W, PV.Y, PV.X, PV.Z, +; EG-NEXT: SETGT_INT * T5.W, T0.X, literal.z, +; EG-NEXT: 31(4.344025e-44), 8388608(1.175494e-38) ; EG-NEXT: 23(3.222986e-44), 0(0.000000e+00) -; EG-NEXT: CNDE_INT T2.X, PS, 0.0, PV.W, -; EG-NEXT: OR_INT T1.Y, PV.Z, literal.x, -; EG-NEXT: ADD_INT T0.Z, T2.W, literal.y, -; EG-NEXT: CNDE_INT T1.W, PV.X, PV.Y, 0.0, -; EG-NEXT: CNDE_INT * T3.W, T2.Z, T3.W, 0.0, -; EG-NEXT: 8388608(1.175494e-38), -150(nan) -; EG-NEXT: CNDE_INT T1.X, T4.W, PV.W, PS, -; EG-NEXT: ASHR T2.Y, KC0[4].X, literal.x, -; EG-NEXT: AND_INT T1.Z, PV.Z, literal.x, -; EG-NEXT: NOT_INT T1.W, PV.Z, -; EG-NEXT: LSHR * T3.W, PV.Y, 1, -; EG-NEXT: 31(4.344025e-44), 0(0.000000e+00) -; EG-NEXT: BIT_ALIGN_INT T3.X, 0.0, PS, PV.W, -; EG-NEXT: LSHL T3.Y, T1.Y, PV.Z, -; EG-NEXT: XOR_INT T1.Z, PV.X, PV.Y, -; EG-NEXT: XOR_INT T1.W, T2.X, PV.Y, -; EG-NEXT: SUB_INT * T2.W, literal.x, T2.W, -; EG-NEXT: 150(2.101948e-43), 0(0.000000e+00) -; EG-NEXT: AND_INT T1.X, T0.Z, literal.x, -; EG-NEXT: AND_INT T4.Y, PS, literal.x, -; EG-NEXT: BIT_ALIGN_INT T0.Z, 0.0, T1.Y, PS, BS:VEC_021/SCL_122 -; EG-NEXT: SUB_INT T1.W, PV.W, T2.Y, -; EG-NEXT: SUBB_UINT * T2.W, PV.Z, T2.Y, -; EG-NEXT: 32(4.484155e-44), 0(0.000000e+00) -; EG-NEXT: SUB_INT T2.X, PV.W, PS, -; EG-NEXT: CNDE_INT T1.Y, PV.Y, PV.Z, 0.0, -; EG-NEXT: CNDE_INT T0.Z, PV.X, T3.Y, 0.0, -; EG-NEXT: CNDE_INT T1.W, PV.X, T3.X, T3.Y, BS:VEC_021/SCL_122 -; EG-NEXT: SETGT_INT * T2.W, T0.Y, literal.x, +; EG-NEXT: CNDE_INT T3.Y, PS, 0.0, PV.W, +; EG-NEXT: SUB_INT T2.Z, literal.x, T1.W, +; EG-NEXT: LSHL T1.W, PV.Z, PV.Y, +; EG-NEXT: AND_INT * T3.W, T4.W, literal.y, +; EG-NEXT: 150(2.101948e-43), 32(4.484155e-44) +; EG-NEXT: CNDE_INT T1.X, PS, PV.W, 0.0, +; EG-NEXT: AND_INT T2.Y, PV.Z, literal.x, +; EG-NEXT: SUB_INT T3.Z, literal.y, T0.Y, +; EG-NEXT: NOT_INT T4.W, T4.W, +; EG-NEXT: LSHR * T6.W, T1.Z, 1, +; EG-NEXT: 32(4.484155e-44), 150(2.101948e-43) +; EG-NEXT: BIT_ALIGN_INT T2.X, 0.0, T2.W, T2.Z, +; EG-NEXT: ADD_INT T0.Y, T0.Y, literal.x, +; EG-NEXT: BIT_ALIGN_INT T2.Z, 0.0, PS, PV.W, +; EG-NEXT: BIT_ALIGN_INT T2.W, 0.0, T1.Z, PV.Z, +; EG-NEXT: AND_INT * T4.W, PV.Z, literal.y, +; EG-NEXT: -127(nan), 32(4.484155e-44) +; EG-NEXT: CNDE_INT T3.X, PS, PV.W, 0.0, +; EG-NEXT: CNDE_INT T4.Y, T3.W, PV.Z, T1.W, +; EG-NEXT: SETGT_INT T1.Z, PV.Y, literal.x, +; EG-NEXT: CNDE_INT T1.W, T1.Y, T0.Z, 0.0, +; EG-NEXT: CNDE_INT * T2.W, T2.Y, PV.X, 0.0, ; EG-NEXT: 23(3.222986e-44), 0(0.000000e+00) -; EG-NEXT: BFE_UINT T1.X, KC0[3].W, literal.x, T0.W, -; EG-NEXT: AND_INT T3.Y, KC0[3].W, literal.y, -; EG-NEXT: CNDE_INT T2.Z, PS, 0.0, PV.W, -; EG-NEXT: CNDE_INT T1.W, PS, PV.Y, PV.Z, -; EG-NEXT: ASHR * T2.W, KC0[3].Z, literal.z, -; EG-NEXT: 23(3.222986e-44), 8388607(1.175494e-38) +; EG-NEXT: CNDE_INT T2.X, T5.W, PS, PV.W, +; EG-NEXT: ASHR T1.Y, KC0[3].Z, literal.x, +; EG-NEXT: CNDE_INT T0.Z, PV.Z, 0.0, PV.Y, +; EG-NEXT: CNDE_INT T1.W, PV.Z, PV.X, T1.X, +; EG-NEXT: ASHR * T2.W, KC0[4].X, literal.x, ; EG-NEXT: 31(4.344025e-44), 0(0.000000e+00) -; EG-NEXT: BFE_UINT T3.X, KC0[3].Y, literal.x, T0.W, -; EG-NEXT: XOR_INT T1.Y, PV.W, PS, +; EG-NEXT: XOR_INT T2.Y, PV.W, PS, ; EG-NEXT: XOR_INT T0.Z, PV.Z, PS, -; EG-NEXT: OR_INT T0.W, PV.Y, literal.y, -; EG-NEXT: SUB_INT * T1.W, literal.z, PV.X, -; EG-NEXT: 23(3.222986e-44), 8388608(1.175494e-38) +; EG-NEXT: XOR_INT T1.W, PV.X, PV.Y, +; EG-NEXT: XOR_INT * T3.W, T3.Y, PV.Y, +; EG-NEXT: SUB_INT T3.Y, PS, T1.Y, +; EG-NEXT: SUBB_UINT T1.Z, PV.W, T1.Y, +; EG-NEXT: SUB_INT T3.W, PV.Z, T2.W, +; EG-NEXT: SUBB_UINT * T4.W, PV.Y, T2.W, +; EG-NEXT: SUB_INT T4.Y, PV.W, PS, +; EG-NEXT: SUB_INT T0.Z, PV.Y, PV.Z, +; EG-NEXT: BFE_UINT T3.W, KC0[3].Y, literal.x, T0.W, +; EG-NEXT: AND_INT * T4.W, KC0[3].Y, literal.y, +; EG-NEXT: 23(3.222986e-44), 8388607(1.175494e-38) +; EG-NEXT: SETGT_INT T0.X, 0.0, T0.X, +; EG-NEXT: ADD_INT T3.Y, PV.W, literal.x, +; EG-NEXT: OR_INT T1.Z, PS, literal.y, +; EG-NEXT: BFE_UINT T0.W, KC0[3].W, literal.z, T0.W, +; EG-NEXT: ADD_INT * T4.W, PV.W, literal.w, +; EG-NEXT: -127(nan), 8388608(1.175494e-38) +; EG-NEXT: 23(3.222986e-44), -150(nan) +; EG-NEXT: AND_INT T1.X, KC0[3].W, literal.x, +; EG-NEXT: ADD_INT T5.Y, PV.W, literal.y, +; EG-NEXT: SUB_INT T2.Z, literal.z, T3.W, +; EG-NEXT: NOT_INT T3.W, PS, +; EG-NEXT: LSHR * T5.W, PV.Z, 1, +; EG-NEXT: 8388607(1.175494e-38), -150(nan) ; EG-NEXT: 150(2.101948e-43), 0(0.000000e+00) -; EG-NEXT: AND_INT T4.X, KC0[3].Y, literal.x, -; EG-NEXT: AND_INT T3.Y, PS, literal.y, -; EG-NEXT: BIT_ALIGN_INT T2.Z, 0.0, PV.W, PS, -; EG-NEXT: SUB_INT T1.W, PV.Z, T2.W, -; EG-NEXT: SUBB_UINT * T3.W, PV.Y, T2.W, -; EG-NEXT: 8388607(1.175494e-38), 32(4.484155e-44) -; EG-NEXT: SUB_INT T5.X, PV.W, PS, -; EG-NEXT: SETGT_INT T0.Y, 0.0, T0.Y, -; EG-NEXT: CNDE_INT T0.Z, PV.Y, PV.Z, 0.0, -; EG-NEXT: OR_INT T1.W, PV.X, literal.x, -; EG-NEXT: ADD_INT * T3.W, T3.X, literal.y, -; EG-NEXT: 8388608(1.175494e-38), -150(nan) -; EG-NEXT: ADD_INT T4.X, T3.X, literal.x, -; EG-NEXT: SUB_INT T3.Y, literal.y, T3.X, -; EG-NEXT: AND_INT T2.Z, PS, literal.z, -; EG-NEXT: NOT_INT T4.W, PS, -; EG-NEXT: LSHR * T5.W, PV.W, 1, -; EG-NEXT: -127(nan), 150(2.101948e-43) -; EG-NEXT: 31(4.344025e-44), 0(0.000000e+00) -; EG-NEXT: BIT_ALIGN_INT T3.X, 0.0, PS, PV.W, -; EG-NEXT: LSHL T4.Y, T1.W, PV.Z, -; EG-NEXT: AND_INT T2.Z, T3.W, literal.x, BS:VEC_120/SCL_212 -; EG-NEXT: BIT_ALIGN_INT T1.W, 0.0, T1.W, PV.Y, BS:VEC_021/SCL_122 -; EG-NEXT: AND_INT * T3.W, PV.Y, literal.x, +; EG-NEXT: BIT_ALIGN_INT T2.X, 0.0, PS, PV.W, +; EG-NEXT: AND_INT T6.Y, PV.Z, literal.x, +; EG-NEXT: AND_INT T3.Z, PV.Y, literal.y, +; EG-NEXT: OR_INT T3.W, PV.X, literal.z, +; EG-NEXT: AND_INT * T5.W, T4.W, literal.y, +; EG-NEXT: 32(4.484155e-44), 31(4.344025e-44) +; EG-NEXT: 8388608(1.175494e-38), 0(0.000000e+00) +; EG-NEXT: BIT_ALIGN_INT T1.X, 0.0, T1.Z, T2.Z, +; EG-NEXT: LSHL T7.Y, T1.Z, PS, +; EG-NEXT: AND_INT T1.Z, T4.W, literal.x, +; EG-NEXT: LSHL T4.W, PV.W, PV.Z, +; EG-NEXT: AND_INT * T5.W, T5.Y, literal.x, ; EG-NEXT: 32(4.484155e-44), 0(0.000000e+00) -; EG-NEXT: ADD_INT T6.X, T1.X, literal.x, -; EG-NEXT: CNDE_INT T3.Y, PS, PV.W, 0.0, -; EG-NEXT: CNDE_INT * T3.Z, PV.Z, PV.Y, 0.0, -; EG-NEXT: -150(nan), 0(0.000000e+00) -; EG-NEXT: ALU clause starting at 108: -; EG-NEXT: CNDE_INT T1.W, T2.Z, T3.X, T4.Y, -; EG-NEXT: SETGT_INT * T3.W, T4.X, literal.x, +; EG-NEXT: CNDE_INT T3.X, PS, PV.W, 0.0, +; EG-NEXT: CNDE_INT T8.Y, PV.Z, PV.Y, 0.0, +; EG-NEXT: CNDE_INT * T2.Z, T6.Y, PV.X, 0.0, +; EG-NEXT: ALU clause starting at 106: +; EG-NEXT: CNDE_INT T6.W, T1.Z, T2.X, T7.Y, BS:VEC_021/SCL_122 +; EG-NEXT: SETGT_INT * T7.W, T3.Y, literal.x, ; EG-NEXT: 23(3.222986e-44), 0(0.000000e+00) -; EG-NEXT: CNDE_INT T3.X, PS, 0.0, PV.W, -; EG-NEXT: CNDE_INT T3.Y, PS, T3.Y, T3.Z, -; EG-NEXT: AND_INT T2.Z, T6.X, literal.x, -; EG-NEXT: NOT_INT T1.W, T6.X, -; EG-NEXT: LSHR * T3.W, T0.W, 1, -; EG-NEXT: 31(4.344025e-44), 0(0.000000e+00) -; EG-NEXT: ASHR T7.X, KC0[3].Y, literal.x, -; EG-NEXT: ADD_INT T4.Y, T1.X, literal.y, -; EG-NEXT: BIT_ALIGN_INT T3.Z, 0.0, PS, PV.W, -; EG-NEXT: LSHL T0.W, T0.W, PV.Z, -; EG-NEXT: AND_INT * T1.W, T6.X, literal.z, +; EG-NEXT: CNDE_INT T1.X, PS, 0.0, PV.W, +; EG-NEXT: CNDE_INT T6.Y, PS, T2.Z, T8.Y, +; EG-NEXT: SUB_INT T1.Z, literal.x, T0.W, +; EG-NEXT: NOT_INT T6.W, T5.Y, +; EG-NEXT: LSHR * T7.W, T3.W, 1, +; EG-NEXT: 150(2.101948e-43), 0(0.000000e+00) +; EG-NEXT: ASHR T2.X, KC0[3].Y, literal.x, +; EG-NEXT: ADD_INT T5.Y, T0.W, literal.y, +; EG-NEXT: BIT_ALIGN_INT T2.Z, 0.0, PS, PV.W, +; EG-NEXT: BIT_ALIGN_INT T0.W, 0.0, T3.W, PV.Z, +; EG-NEXT: AND_INT * T3.W, PV.Z, literal.z, ; EG-NEXT: 31(4.344025e-44), -127(nan) ; EG-NEXT: 32(4.484155e-44), 0(0.000000e+00) -; EG-NEXT: CNDE_INT T1.X, PS, PV.W, 0.0, -; EG-NEXT: CNDE_INT T5.Y, PS, PV.Z, PV.W, -; EG-NEXT: SETGT_INT T2.Z, PV.Y, literal.x, -; EG-NEXT: XOR_INT T0.W, T3.Y, PV.X, -; EG-NEXT: XOR_INT * T1.W, T3.X, PV.X, +; EG-NEXT: CNDE_INT T4.X, PS, PV.W, 0.0, +; EG-NEXT: CNDE_INT T7.Y, T5.W, PV.Z, T4.W, +; EG-NEXT: SETGT_INT T1.Z, PV.Y, literal.x, +; EG-NEXT: XOR_INT T0.W, T6.Y, PV.X, +; EG-NEXT: XOR_INT * T3.W, T1.X, PV.X, ; EG-NEXT: 23(3.222986e-44), 0(0.000000e+00) -; EG-NEXT: SUB_INT T3.X, PS, T7.X, -; EG-NEXT: SUBB_UINT T3.Y, PV.W, T7.X, -; EG-NEXT: CNDE_INT T3.Z, PV.Z, 0.0, PV.Y, -; EG-NEXT: CNDE_INT T1.W, PV.Z, T0.Z, PV.X, -; EG-NEXT: ASHR * T3.W, KC0[3].W, literal.x, +; EG-NEXT: SUB_INT T1.X, PS, T2.X, +; EG-NEXT: SUBB_UINT T6.Y, PV.W, T2.X, +; EG-NEXT: CNDE_INT T2.Z, PV.Z, 0.0, PV.Y, +; EG-NEXT: CNDE_INT T3.W, PV.Z, PV.X, T3.X, +; EG-NEXT: ASHR * T4.W, KC0[3].W, literal.x, ; EG-NEXT: 31(4.344025e-44), 0(0.000000e+00) -; EG-NEXT: XOR_INT T1.X, PV.W, PS, -; EG-NEXT: XOR_INT T5.Y, PV.Z, PS, -; EG-NEXT: SUB_INT T0.Z, PV.X, PV.Y, -; EG-NEXT: SETGT_INT T1.W, 0.0, T4.X, BS:VEC_021/SCL_122 -; EG-NEXT: CNDE_INT * T6.W, T0.Y, T5.X, 0.0, -; EG-NEXT: SETGT_INT T0.X, 0.0, T0.X, +; EG-NEXT: XOR_INT T3.X, PV.W, PS, +; EG-NEXT: XOR_INT T7.Y, PV.Z, PS, +; EG-NEXT: SUB_INT T1.Z, PV.X, PV.Y, +; EG-NEXT: SETGT_INT T3.W, 0.0, T3.Y, +; EG-NEXT: CNDE_INT * T6.W, T0.X, T0.Z, 0.0, +; EG-NEXT: SETGT_INT T1.X, 0.0, T0.Y, ; EG-NEXT: CNDE_INT T6.Y, PV.W, PV.Z, 0.0, -; EG-NEXT: SUB_INT T0.Z, T1.Y, T2.W, BS:VEC_021/SCL_122 -; EG-NEXT: SUB_INT T2.W, PV.Y, T3.W, -; EG-NEXT: SUBB_UINT * T4.W, PV.X, T3.W, -; EG-NEXT: SUB_INT T3.X, PV.W, PS, -; EG-NEXT: SETGT_INT T1.Y, 0.0, T4.Y, -; EG-NEXT: CNDE_INT T6.Z, T0.Y, PV.Z, 0.0, -; EG-NEXT: SUB_INT T0.W, T0.W, T7.X, BS:VEC_021/SCL_122 -; EG-NEXT: CNDE_INT * T4.W, PV.X, T2.X, 0.0, -; EG-NEXT: CNDE_INT T6.X, T1.W, PV.W, 0.0, -; EG-NEXT: CNDE_INT T4.Y, PV.Y, PV.X, 0.0, -; EG-NEXT: SUB_INT T0.W, T1.Z, T2.Y, -; EG-NEXT: LSHR * T2.X, KC0[2].Y, literal.x, +; EG-NEXT: SUB_INT T0.Z, T1.W, T1.Y, BS:VEC_021/SCL_122 +; EG-NEXT: SUB_INT T1.W, PV.Y, T4.W, +; EG-NEXT: SUBB_UINT * T5.W, PV.X, T4.W, +; EG-NEXT: SUB_INT T4.X, PV.W, PS, +; EG-NEXT: SETGT_INT T0.Y, 0.0, T5.Y, BS:VEC_021/SCL_122 +; EG-NEXT: CNDE_INT T6.Z, T0.X, PV.Z, 0.0, +; EG-NEXT: SUB_INT T0.W, T0.W, T2.X, +; EG-NEXT: CNDE_INT * T1.W, PV.X, T4.Y, 0.0, +; EG-NEXT: CNDE_INT T6.X, T3.W, PV.W, 0.0, +; EG-NEXT: CNDE_INT T1.Y, PV.Y, PV.X, 0.0, +; EG-NEXT: SUB_INT T0.W, T2.Y, T2.W, +; EG-NEXT: LSHR * T0.X, KC0[2].Y, literal.x, ; EG-NEXT: 2(2.802597e-45), 0(0.000000e+00) -; EG-NEXT: CNDE_INT T4.Z, T0.X, PV.W, 0.0, -; EG-NEXT: SUB_INT * T0.W, T1.X, T3.W, BS:VEC_120/SCL_212 -; EG-NEXT: CNDE_INT T4.X, T1.Y, PV.W, 0.0, +; EG-NEXT: CNDE_INT T1.Z, T1.X, PV.W, 0.0, +; EG-NEXT: SUB_INT * T0.W, T3.X, T4.W, BS:VEC_120/SCL_212 +; EG-NEXT: CNDE_INT T1.X, T0.Y, PV.W, 0.0, ; EG-NEXT: ADD_INT * T0.W, KC0[2].Y, literal.x, ; EG-NEXT: 16(2.242078e-44), 0(0.000000e+00) -; EG-NEXT: LSHR * T0.X, PV.W, literal.x, +; EG-NEXT: LSHR * T2.X, PV.W, literal.x, ; EG-NEXT: 2(2.802597e-45), 0(0.000000e+00) %conv = fptosi <4 x float> %x to <4 x i64> store <4 x i64> %conv, ptr addrspace(1) %out diff --git a/llvm/test/CodeGen/AMDGPU/fp_to_uint.ll b/llvm/test/CodeGen/AMDGPU/fp_to_uint.ll index 5170f9c76db2..5abf82aa1aab 100644 --- a/llvm/test/CodeGen/AMDGPU/fp_to_uint.ll +++ b/llvm/test/CodeGen/AMDGPU/fp_to_uint.ll @@ -200,25 +200,25 @@ define amdgpu_kernel void @fp_to_uint_f32_to_i64(ptr addrspace(1) %out, float %x ; EG-NEXT: ADD_INT * T2.W, PV.W, literal.y, ; EG-NEXT: 8388608(1.175494e-38), -150(nan) ; EG-NEXT: ADD_INT T0.X, T0.W, literal.x, -; EG-NEXT: SUB_INT T0.Y, literal.y, T0.W, -; EG-NEXT: AND_INT T0.Z, PS, literal.z, +; EG-NEXT: AND_INT T0.Y, PS, literal.y, +; EG-NEXT: SUB_INT T0.Z, literal.z, T0.W, ; EG-NEXT: NOT_INT T0.W, PS, ; EG-NEXT: LSHR * T3.W, PV.W, 1, -; EG-NEXT: -127(nan), 150(2.101948e-43) -; EG-NEXT: 31(4.344025e-44), 0(0.000000e+00) +; EG-NEXT: -127(nan), 31(4.344025e-44) +; EG-NEXT: 150(2.101948e-43), 0(0.000000e+00) ; EG-NEXT: BIT_ALIGN_INT T1.X, 0.0, PS, PV.W, -; EG-NEXT: LSHL T1.Y, T1.W, PV.Z, -; EG-NEXT: AND_INT T0.Z, T2.W, literal.x, BS:VEC_120/SCL_212 -; EG-NEXT: BIT_ALIGN_INT T0.W, 0.0, T1.W, PV.Y, BS:VEC_021/SCL_122 -; EG-NEXT: AND_INT * T1.W, PV.Y, literal.x, +; EG-NEXT: AND_INT T1.Y, PV.Z, literal.x, +; EG-NEXT: BIT_ALIGN_INT T0.Z, 0.0, T1.W, PV.Z, +; EG-NEXT: LSHL T0.W, T1.W, PV.Y, +; EG-NEXT: AND_INT * T1.W, T2.W, literal.x, ; EG-NEXT: 32(4.484155e-44), 0(0.000000e+00) ; EG-NEXT: CNDE_INT T0.Y, PS, PV.W, 0.0, -; EG-NEXT: CNDE_INT T1.Z, PV.Z, PV.Y, 0.0, -; EG-NEXT: CNDE_INT T0.W, PV.Z, PV.X, PV.Y, +; EG-NEXT: CNDE_INT T0.Z, PV.Y, PV.Z, 0.0, +; EG-NEXT: CNDE_INT T0.W, PS, PV.X, PV.W, ; EG-NEXT: SETGT_INT * T1.W, T0.X, literal.x, ; EG-NEXT: 23(3.222986e-44), 0(0.000000e+00) -; EG-NEXT: CNDE_INT T0.Z, PS, 0.0, PV.W, -; EG-NEXT: CNDE_INT T0.W, PS, PV.Y, PV.Z, +; EG-NEXT: CNDE_INT T1.Z, PS, 0.0, PV.W, +; EG-NEXT: CNDE_INT T0.W, PS, PV.Z, PV.Y, ; EG-NEXT: ASHR * T1.W, KC0[2].Z, literal.x, ; EG-NEXT: 31(4.344025e-44), 0(0.000000e+00) ; EG-NEXT: XOR_INT T0.W, PV.W, PS, @@ -288,79 +288,78 @@ define amdgpu_kernel void @fp_to_uint_v2f32_to_v2i64(ptr addrspace(1) %out, <2 x ; ; EG-LABEL: fp_to_uint_v2f32_to_v2i64: ; EG: ; %bb.0: -; EG-NEXT: ALU 75, @4, KC0[CB0:0-32], KC1[] +; EG-NEXT: ALU 74, @4, KC0[CB0:0-32], KC1[] ; EG-NEXT: MEM_RAT_CACHELESS STORE_RAW T1.XYZW, T0.X, 1 ; EG-NEXT: CF_END ; EG-NEXT: PAD ; EG-NEXT: ALU clause starting at 4: ; EG-NEXT: MOV * T0.W, literal.x, ; EG-NEXT: 8(1.121039e-44), 0(0.000000e+00) -; EG-NEXT: BFE_UINT * T1.W, KC0[2].W, literal.x, PV.W, -; EG-NEXT: 23(3.222986e-44), 0(0.000000e+00) -; EG-NEXT: AND_INT T0.Z, KC0[2].W, literal.x, -; EG-NEXT: BFE_UINT T0.W, KC0[3].X, literal.y, T0.W, -; EG-NEXT: ADD_INT * T2.W, PV.W, literal.z, -; EG-NEXT: 8388607(1.175494e-38), 23(3.222986e-44) +; EG-NEXT: BFE_UINT T0.Z, KC0[3].X, literal.x, PV.W, +; EG-NEXT: BFE_UINT T0.W, KC0[2].W, literal.x, PV.W, +; EG-NEXT: AND_INT * T1.Z, KC0[2].W, literal.y, +; EG-NEXT: 23(3.222986e-44), 8388607(1.175494e-38) +; EG-NEXT: ADD_INT T1.W, PV.W, literal.x, +; EG-NEXT: ADD_INT * T2.W, PV.Z, literal.x, ; EG-NEXT: -150(nan), 0(0.000000e+00) -; EG-NEXT: SUB_INT T0.X, literal.x, PV.W, -; EG-NEXT: SUB_INT T0.Y, literal.x, T1.W, -; EG-NEXT: AND_INT T1.Z, PS, literal.y, -; EG-NEXT: OR_INT T3.W, PV.Z, literal.z, +; EG-NEXT: AND_INT T0.X, PS, literal.x, +; EG-NEXT: AND_INT T0.Y, PV.W, literal.x, +; EG-NEXT: OR_INT T1.Z, T1.Z, literal.y, +; EG-NEXT: SUB_INT T3.W, literal.z, T0.W, ; EG-NEXT: AND_INT * T4.W, KC0[3].X, literal.w, -; EG-NEXT: 150(2.101948e-43), 31(4.344025e-44) -; EG-NEXT: 8388608(1.175494e-38), 8388607(1.175494e-38) +; EG-NEXT: 31(4.344025e-44), 8388608(1.175494e-38) +; EG-NEXT: 150(2.101948e-43), 8388607(1.175494e-38) ; EG-NEXT: OR_INT T1.X, PS, literal.x, -; EG-NEXT: LSHL T1.Y, PV.W, PV.Z, -; EG-NEXT: AND_INT T0.Z, T2.W, literal.y, -; EG-NEXT: BIT_ALIGN_INT T4.W, 0.0, PV.W, PV.Y, -; EG-NEXT: AND_INT * T5.W, PV.Y, literal.y, +; EG-NEXT: AND_INT T1.Y, PV.W, literal.y, +; EG-NEXT: BIT_ALIGN_INT T2.Z, 0.0, PV.Z, PV.W, +; EG-NEXT: LSHL T3.W, PV.Z, PV.Y, +; EG-NEXT: AND_INT * T4.W, T1.W, literal.y, ; EG-NEXT: 8388608(1.175494e-38), 32(4.484155e-44) -; EG-NEXT: CNDE_INT T2.X, PS, PV.W, 0.0, -; EG-NEXT: CNDE_INT T0.Y, PV.Z, PV.Y, 0.0, -; EG-NEXT: ADD_INT T1.Z, T0.W, literal.x, -; EG-NEXT: BIT_ALIGN_INT T4.W, 0.0, PV.X, T0.X, -; EG-NEXT: AND_INT * T5.W, T0.X, literal.y, -; EG-NEXT: -150(nan), 32(4.484155e-44) +; EG-NEXT: CNDE_INT T0.Y, PS, PV.W, 0.0, +; EG-NEXT: CNDE_INT T2.Z, PV.Y, PV.Z, 0.0, +; EG-NEXT: LSHL T5.W, PV.X, T0.X, +; EG-NEXT: AND_INT * T6.W, T2.W, literal.x, +; EG-NEXT: 32(4.484155e-44), 0(0.000000e+00) ; EG-NEXT: CNDE_INT T0.X, PS, PV.W, 0.0, -; EG-NEXT: NOT_INT T2.Y, T2.W, -; EG-NEXT: AND_INT T2.Z, PV.Z, literal.x, -; EG-NEXT: NOT_INT T2.W, PV.Z, -; EG-NEXT: LSHR * T4.W, T1.X, 1, -; EG-NEXT: 31(4.344025e-44), 0(0.000000e+00) -; EG-NEXT: LSHR T3.X, T3.W, 1, -; EG-NEXT: ADD_INT T3.Y, T0.W, literal.x, BS:VEC_120/SCL_212 -; EG-NEXT: BIT_ALIGN_INT T3.Z, 0.0, PS, PV.W, -; EG-NEXT: LSHL T0.W, T1.X, PV.Z, -; EG-NEXT: AND_INT * T2.W, T1.Z, literal.y, +; EG-NEXT: NOT_INT T1.Y, T1.W, +; EG-NEXT: SUB_INT T3.Z, literal.x, T0.Z, +; EG-NEXT: NOT_INT T1.W, T2.W, BS:VEC_120/SCL_212 +; EG-NEXT: LSHR * T2.W, T1.X, 1, +; EG-NEXT: 150(2.101948e-43), 0(0.000000e+00) +; EG-NEXT: LSHR T2.X, T1.Z, 1, +; EG-NEXT: ADD_INT T2.Y, T0.Z, literal.x, BS:VEC_120/SCL_212 +; EG-NEXT: BIT_ALIGN_INT T0.Z, 0.0, PS, PV.W, +; EG-NEXT: BIT_ALIGN_INT T1.W, 0.0, T1.X, PV.Z, +; EG-NEXT: AND_INT * T2.W, PV.Z, literal.y, ; EG-NEXT: -127(nan), 32(4.484155e-44) ; EG-NEXT: CNDE_INT T1.X, PS, PV.W, 0.0, -; EG-NEXT: CNDE_INT T4.Y, PS, PV.Z, PV.W, -; EG-NEXT: SETGT_INT T1.Z, PV.Y, literal.x, -; EG-NEXT: BIT_ALIGN_INT T0.W, 0.0, PV.X, T2.Y, -; EG-NEXT: ADD_INT * T1.W, T1.W, literal.y, +; EG-NEXT: CNDE_INT T3.Y, T6.W, PV.Z, T5.W, BS:VEC_021/SCL_122 +; EG-NEXT: SETGT_INT T0.Z, PV.Y, literal.x, +; EG-NEXT: BIT_ALIGN_INT T1.W, 0.0, PV.X, T1.Y, +; EG-NEXT: ADD_INT * T0.W, T0.W, literal.y, ; EG-NEXT: 23(3.222986e-44), -127(nan) -; EG-NEXT: CNDE_INT T3.X, T0.Z, PV.W, T1.Y, +; EG-NEXT: CNDE_INT T2.X, T4.W, PV.W, T3.W, ; EG-NEXT: SETGT_INT T1.Y, PS, literal.x, -; EG-NEXT: CNDE_INT T0.Z, PV.Z, 0.0, PV.Y, -; EG-NEXT: CNDE_INT T0.W, PV.Z, T0.X, PV.X, +; EG-NEXT: CNDE_INT T1.Z, PV.Z, 0.0, PV.Y, +; EG-NEXT: CNDE_INT T1.W, PV.Z, PV.X, T0.X, ; EG-NEXT: ASHR * T2.W, KC0[3].X, literal.y, ; EG-NEXT: 23(3.222986e-44), 31(4.344025e-44) ; EG-NEXT: XOR_INT T0.X, PV.W, PS, -; EG-NEXT: XOR_INT T2.Y, PV.Z, PS, +; EG-NEXT: XOR_INT T3.Y, PV.Z, PS, ; EG-NEXT: CNDE_INT T0.Z, PV.Y, 0.0, PV.X, -; EG-NEXT: CNDE_INT T0.W, PV.Y, T2.X, T0.Y, +; EG-NEXT: CNDE_INT T1.W, PV.Y, T2.Z, T0.Y, ; EG-NEXT: ASHR * T3.W, KC0[2].W, literal.x, ; EG-NEXT: 31(4.344025e-44), 0(0.000000e+00) ; EG-NEXT: XOR_INT T0.Y, PV.W, PS, ; EG-NEXT: XOR_INT T0.Z, PV.Z, PS, -; EG-NEXT: SUB_INT T0.W, PV.Y, T2.W, +; EG-NEXT: SUB_INT T1.W, PV.Y, T2.W, ; EG-NEXT: SUBB_UINT * T4.W, PV.X, T2.W, ; EG-NEXT: SUB_INT T1.Y, PV.W, PS, -; EG-NEXT: SETGT_INT T1.Z, 0.0, T3.Y, -; EG-NEXT: SUB_INT T0.W, PV.Z, T3.W, +; EG-NEXT: SETGT_INT T1.Z, 0.0, T2.Y, +; EG-NEXT: SUB_INT T1.W, PV.Z, T3.W, ; EG-NEXT: SUBB_UINT * T4.W, PV.Y, T3.W, ; EG-NEXT: SUB_INT T0.Z, PV.W, PS, -; EG-NEXT: SETGT_INT T0.W, 0.0, T1.W, +; EG-NEXT: SETGT_INT T0.W, 0.0, T0.W, ; EG-NEXT: CNDE_INT * T1.W, PV.Z, PV.Y, 0.0, ; EG-NEXT: CNDE_INT T1.Y, PV.W, PV.Z, 0.0, ; EG-NEXT: SUB_INT * T2.W, T0.X, T2.W, @@ -449,170 +448,168 @@ define amdgpu_kernel void @fp_to_uint_v4f32_to_v4i64(ptr addrspace(1) %out, <4 x ; ; EG-LABEL: fp_to_uint_v4f32_to_v4i64: ; EG: ; %bb.0: -; EG-NEXT: ALU 101, @6, KC0[CB0:0-32], KC1[] -; EG-NEXT: ALU 54, @108, KC0[CB0:0-32], KC1[] -; EG-NEXT: MEM_RAT_CACHELESS STORE_RAW T4.XYZW, T0.X, 0 -; EG-NEXT: MEM_RAT_CACHELESS STORE_RAW T6.XYZW, T2.X, 1 +; EG-NEXT: ALU 99, @6, KC0[CB0:0-32], KC1[] +; EG-NEXT: ALU 54, @106, KC0[CB0:0-32], KC1[] +; EG-NEXT: MEM_RAT_CACHELESS STORE_RAW T1.XYZW, T2.X, 0 +; EG-NEXT: MEM_RAT_CACHELESS STORE_RAW T6.XYZW, T0.X, 1 ; EG-NEXT: CF_END ; EG-NEXT: PAD ; EG-NEXT: ALU clause starting at 6: ; EG-NEXT: MOV * T0.W, literal.x, ; EG-NEXT: 8(1.121039e-44), 0(0.000000e+00) -; EG-NEXT: BFE_UINT T1.W, KC0[4].X, literal.x, PV.W, -; EG-NEXT: AND_INT * T2.W, KC0[4].X, literal.y, +; EG-NEXT: BFE_UINT T1.W, KC0[3].Z, literal.x, PV.W, +; EG-NEXT: AND_INT * T2.W, KC0[3].Z, literal.y, ; EG-NEXT: 23(3.222986e-44), 8388607(1.175494e-38) -; EG-NEXT: OR_INT T0.Z, PS, literal.x, -; EG-NEXT: BFE_UINT T2.W, KC0[3].Z, literal.y, T0.W, -; EG-NEXT: ADD_INT * T3.W, PV.W, literal.z, -; EG-NEXT: 8388608(1.175494e-38), 23(3.222986e-44) -; EG-NEXT: -150(nan), 0(0.000000e+00) -; EG-NEXT: ADD_INT T0.Y, PV.W, literal.x, -; EG-NEXT: AND_INT T1.Z, PS, literal.y, -; EG-NEXT: NOT_INT T4.W, PS, -; EG-NEXT: LSHR * T5.W, PV.Z, 1, -; EG-NEXT: -127(nan), 31(4.344025e-44) +; EG-NEXT: OR_INT T2.W, PS, literal.x, +; EG-NEXT: ADD_INT * T3.W, PV.W, literal.y, +; EG-NEXT: 8388608(1.175494e-38), -150(nan) ; EG-NEXT: ADD_INT T0.X, T1.W, literal.x, -; EG-NEXT: BIT_ALIGN_INT T1.Y, 0.0, PS, PV.W, -; EG-NEXT: AND_INT T2.Z, T3.W, literal.y, BS:VEC_201 -; EG-NEXT: LSHL T3.W, T0.Z, PV.Z, -; EG-NEXT: SUB_INT * T1.W, literal.z, T1.W, -; EG-NEXT: -127(nan), 32(4.484155e-44) -; EG-NEXT: 150(2.101948e-43), 0(0.000000e+00) -; EG-NEXT: AND_INT T1.X, PS, literal.x, -; EG-NEXT: BIT_ALIGN_INT T2.Y, 0.0, T0.Z, PS, -; EG-NEXT: AND_INT T0.Z, KC0[3].Z, literal.y, -; EG-NEXT: CNDE_INT T1.W, PV.Z, PV.Y, PV.W, -; EG-NEXT: SETGT_INT * T4.W, PV.X, literal.z, +; EG-NEXT: BFE_UINT T0.Y, KC0[4].X, literal.y, T0.W, +; EG-NEXT: AND_INT T0.Z, PS, literal.z, +; EG-NEXT: NOT_INT T4.W, PS, +; EG-NEXT: LSHR * T5.W, PV.W, 1, +; EG-NEXT: -127(nan), 23(3.222986e-44) +; EG-NEXT: 31(4.344025e-44), 0(0.000000e+00) +; EG-NEXT: BIT_ALIGN_INT T1.X, 0.0, PS, PV.W, +; EG-NEXT: AND_INT T1.Y, T3.W, literal.x, +; EG-NEXT: LSHL T0.Z, T2.W, PV.Z, BS:VEC_120/SCL_212 +; EG-NEXT: AND_INT T3.W, KC0[4].X, literal.y, +; EG-NEXT: ADD_INT * T4.W, PV.Y, literal.z, ; EG-NEXT: 32(4.484155e-44), 8388607(1.175494e-38) +; EG-NEXT: -150(nan), 0(0.000000e+00) +; EG-NEXT: AND_INT T2.Y, PS, literal.x, +; EG-NEXT: OR_INT T1.Z, PV.W, literal.y, +; EG-NEXT: CNDE_INT T3.W, PV.Y, PV.X, PV.Z, +; EG-NEXT: SETGT_INT * T5.W, T0.X, literal.z, +; EG-NEXT: 31(4.344025e-44), 8388608(1.175494e-38) ; EG-NEXT: 23(3.222986e-44), 0(0.000000e+00) -; EG-NEXT: CNDE_INT T2.X, PS, 0.0, PV.W, -; EG-NEXT: OR_INT T1.Y, PV.Z, literal.x, -; EG-NEXT: ADD_INT T0.Z, T2.W, literal.y, -; EG-NEXT: CNDE_INT T1.W, PV.X, PV.Y, 0.0, -; EG-NEXT: CNDE_INT * T3.W, T2.Z, T3.W, 0.0, -; EG-NEXT: 8388608(1.175494e-38), -150(nan) -; EG-NEXT: CNDE_INT T1.X, T4.W, PV.W, PS, -; EG-NEXT: ASHR T2.Y, KC0[4].X, literal.x, -; EG-NEXT: AND_INT T1.Z, PV.Z, literal.x, -; EG-NEXT: NOT_INT T1.W, PV.Z, -; EG-NEXT: LSHR * T3.W, PV.Y, 1, -; EG-NEXT: 31(4.344025e-44), 0(0.000000e+00) -; EG-NEXT: BIT_ALIGN_INT T3.X, 0.0, PS, PV.W, -; EG-NEXT: LSHL T3.Y, T1.Y, PV.Z, -; EG-NEXT: XOR_INT T1.Z, PV.X, PV.Y, -; EG-NEXT: XOR_INT T1.W, T2.X, PV.Y, -; EG-NEXT: SUB_INT * T2.W, literal.x, T2.W, -; EG-NEXT: 150(2.101948e-43), 0(0.000000e+00) -; EG-NEXT: AND_INT T1.X, T0.Z, literal.x, -; EG-NEXT: AND_INT T4.Y, PS, literal.x, -; EG-NEXT: BIT_ALIGN_INT T0.Z, 0.0, T1.Y, PS, BS:VEC_021/SCL_122 -; EG-NEXT: SUB_INT T1.W, PV.W, T2.Y, -; EG-NEXT: SUBB_UINT * T2.W, PV.Z, T2.Y, -; EG-NEXT: 32(4.484155e-44), 0(0.000000e+00) -; EG-NEXT: SUB_INT T2.X, PV.W, PS, -; EG-NEXT: CNDE_INT T1.Y, PV.Y, PV.Z, 0.0, -; EG-NEXT: CNDE_INT T0.Z, PV.X, T3.Y, 0.0, -; EG-NEXT: CNDE_INT T1.W, PV.X, T3.X, T3.Y, BS:VEC_021/SCL_122 -; EG-NEXT: SETGT_INT * T2.W, T0.Y, literal.x, +; EG-NEXT: CNDE_INT T3.Y, PS, 0.0, PV.W, +; EG-NEXT: SUB_INT T2.Z, literal.x, T1.W, +; EG-NEXT: LSHL T1.W, PV.Z, PV.Y, +; EG-NEXT: AND_INT * T3.W, T4.W, literal.y, +; EG-NEXT: 150(2.101948e-43), 32(4.484155e-44) +; EG-NEXT: CNDE_INT T1.X, PS, PV.W, 0.0, +; EG-NEXT: AND_INT T2.Y, PV.Z, literal.x, +; EG-NEXT: SUB_INT T3.Z, literal.y, T0.Y, +; EG-NEXT: NOT_INT T4.W, T4.W, +; EG-NEXT: LSHR * T6.W, T1.Z, 1, +; EG-NEXT: 32(4.484155e-44), 150(2.101948e-43) +; EG-NEXT: BIT_ALIGN_INT T2.X, 0.0, T2.W, T2.Z, +; EG-NEXT: ADD_INT T0.Y, T0.Y, literal.x, +; EG-NEXT: BIT_ALIGN_INT T2.Z, 0.0, PS, PV.W, +; EG-NEXT: BIT_ALIGN_INT T2.W, 0.0, T1.Z, PV.Z, +; EG-NEXT: AND_INT * T4.W, PV.Z, literal.y, +; EG-NEXT: -127(nan), 32(4.484155e-44) +; EG-NEXT: CNDE_INT T3.X, PS, PV.W, 0.0, +; EG-NEXT: CNDE_INT T4.Y, T3.W, PV.Z, T1.W, +; EG-NEXT: SETGT_INT T1.Z, PV.Y, literal.x, +; EG-NEXT: CNDE_INT T1.W, T1.Y, T0.Z, 0.0, +; EG-NEXT: CNDE_INT * T2.W, T2.Y, PV.X, 0.0, ; EG-NEXT: 23(3.222986e-44), 0(0.000000e+00) -; EG-NEXT: BFE_UINT T1.X, KC0[3].W, literal.x, T0.W, -; EG-NEXT: AND_INT T3.Y, KC0[3].W, literal.y, -; EG-NEXT: CNDE_INT T2.Z, PS, 0.0, PV.W, -; EG-NEXT: CNDE_INT T1.W, PS, PV.Y, PV.Z, -; EG-NEXT: ASHR * T2.W, KC0[3].Z, literal.z, -; EG-NEXT: 23(3.222986e-44), 8388607(1.175494e-38) +; EG-NEXT: CNDE_INT T2.X, T5.W, PS, PV.W, +; EG-NEXT: ASHR T1.Y, KC0[3].Z, literal.x, +; EG-NEXT: CNDE_INT T0.Z, PV.Z, 0.0, PV.Y, +; EG-NEXT: CNDE_INT T1.W, PV.Z, PV.X, T1.X, +; EG-NEXT: ASHR * T2.W, KC0[4].X, literal.x, ; EG-NEXT: 31(4.344025e-44), 0(0.000000e+00) -; EG-NEXT: BFE_UINT T3.X, KC0[3].Y, literal.x, T0.W, -; EG-NEXT: XOR_INT T1.Y, PV.W, PS, +; EG-NEXT: XOR_INT T2.Y, PV.W, PS, ; EG-NEXT: XOR_INT T0.Z, PV.Z, PS, -; EG-NEXT: OR_INT T0.W, PV.Y, literal.y, -; EG-NEXT: SUB_INT * T1.W, literal.z, PV.X, -; EG-NEXT: 23(3.222986e-44), 8388608(1.175494e-38) +; EG-NEXT: XOR_INT T1.W, PV.X, PV.Y, +; EG-NEXT: XOR_INT * T3.W, T3.Y, PV.Y, +; EG-NEXT: SUB_INT T3.Y, PS, T1.Y, +; EG-NEXT: SUBB_UINT T1.Z, PV.W, T1.Y, +; EG-NEXT: SUB_INT T3.W, PV.Z, T2.W, +; EG-NEXT: SUBB_UINT * T4.W, PV.Y, T2.W, +; EG-NEXT: SUB_INT T4.Y, PV.W, PS, +; EG-NEXT: SUB_INT T0.Z, PV.Y, PV.Z, +; EG-NEXT: BFE_UINT T3.W, KC0[3].Y, literal.x, T0.W, +; EG-NEXT: AND_INT * T4.W, KC0[3].Y, literal.y, +; EG-NEXT: 23(3.222986e-44), 8388607(1.175494e-38) +; EG-NEXT: SETGT_INT T0.X, 0.0, T0.X, +; EG-NEXT: ADD_INT T3.Y, PV.W, literal.x, +; EG-NEXT: OR_INT T1.Z, PS, literal.y, +; EG-NEXT: BFE_UINT T0.W, KC0[3].W, literal.z, T0.W, +; EG-NEXT: ADD_INT * T4.W, PV.W, literal.w, +; EG-NEXT: -127(nan), 8388608(1.175494e-38) +; EG-NEXT: 23(3.222986e-44), -150(nan) +; EG-NEXT: AND_INT T1.X, KC0[3].W, literal.x, +; EG-NEXT: ADD_INT T5.Y, PV.W, literal.y, +; EG-NEXT: SUB_INT T2.Z, literal.z, T3.W, +; EG-NEXT: NOT_INT T3.W, PS, +; EG-NEXT: LSHR * T5.W, PV.Z, 1, +; EG-NEXT: 8388607(1.175494e-38), -150(nan) ; EG-NEXT: 150(2.101948e-43), 0(0.000000e+00) -; EG-NEXT: AND_INT T4.X, KC0[3].Y, literal.x, -; EG-NEXT: AND_INT T3.Y, PS, literal.y, -; EG-NEXT: BIT_ALIGN_INT T2.Z, 0.0, PV.W, PS, -; EG-NEXT: SUB_INT T1.W, PV.Z, T2.W, -; EG-NEXT: SUBB_UINT * T3.W, PV.Y, T2.W, -; EG-NEXT: 8388607(1.175494e-38), 32(4.484155e-44) -; EG-NEXT: SUB_INT T5.X, PV.W, PS, -; EG-NEXT: SETGT_INT T0.Y, 0.0, T0.Y, -; EG-NEXT: CNDE_INT T0.Z, PV.Y, PV.Z, 0.0, -; EG-NEXT: OR_INT T1.W, PV.X, literal.x, -; EG-NEXT: ADD_INT * T3.W, T3.X, literal.y, -; EG-NEXT: 8388608(1.175494e-38), -150(nan) -; EG-NEXT: ADD_INT T4.X, T3.X, literal.x, -; EG-NEXT: SUB_INT T3.Y, literal.y, T3.X, -; EG-NEXT: AND_INT T2.Z, PS, literal.z, -; EG-NEXT: NOT_INT T4.W, PS, -; EG-NEXT: LSHR * T5.W, PV.W, 1, -; EG-NEXT: -127(nan), 150(2.101948e-43) -; EG-NEXT: 31(4.344025e-44), 0(0.000000e+00) -; EG-NEXT: BIT_ALIGN_INT T3.X, 0.0, PS, PV.W, -; EG-NEXT: LSHL T4.Y, T1.W, PV.Z, -; EG-NEXT: AND_INT T2.Z, T3.W, literal.x, BS:VEC_120/SCL_212 -; EG-NEXT: BIT_ALIGN_INT T1.W, 0.0, T1.W, PV.Y, BS:VEC_021/SCL_122 -; EG-NEXT: AND_INT * T3.W, PV.Y, literal.x, +; EG-NEXT: BIT_ALIGN_INT T2.X, 0.0, PS, PV.W, +; EG-NEXT: AND_INT T6.Y, PV.Z, literal.x, +; EG-NEXT: AND_INT T3.Z, PV.Y, literal.y, +; EG-NEXT: OR_INT T3.W, PV.X, literal.z, +; EG-NEXT: AND_INT * T5.W, T4.W, literal.y, +; EG-NEXT: 32(4.484155e-44), 31(4.344025e-44) +; EG-NEXT: 8388608(1.175494e-38), 0(0.000000e+00) +; EG-NEXT: BIT_ALIGN_INT T1.X, 0.0, T1.Z, T2.Z, +; EG-NEXT: LSHL T7.Y, T1.Z, PS, +; EG-NEXT: AND_INT T1.Z, T4.W, literal.x, +; EG-NEXT: LSHL T4.W, PV.W, PV.Z, +; EG-NEXT: AND_INT * T5.W, T5.Y, literal.x, ; EG-NEXT: 32(4.484155e-44), 0(0.000000e+00) -; EG-NEXT: ADD_INT T6.X, T1.X, literal.x, -; EG-NEXT: CNDE_INT T3.Y, PS, PV.W, 0.0, -; EG-NEXT: CNDE_INT * T3.Z, PV.Z, PV.Y, 0.0, -; EG-NEXT: -150(nan), 0(0.000000e+00) -; EG-NEXT: ALU clause starting at 108: -; EG-NEXT: CNDE_INT T1.W, T2.Z, T3.X, T4.Y, -; EG-NEXT: SETGT_INT * T3.W, T4.X, literal.x, +; EG-NEXT: CNDE_INT T3.X, PS, PV.W, 0.0, +; EG-NEXT: CNDE_INT T8.Y, PV.Z, PV.Y, 0.0, +; EG-NEXT: CNDE_INT * T2.Z, T6.Y, PV.X, 0.0, +; EG-NEXT: ALU clause starting at 106: +; EG-NEXT: CNDE_INT T6.W, T1.Z, T2.X, T7.Y, BS:VEC_021/SCL_122 +; EG-NEXT: SETGT_INT * T7.W, T3.Y, literal.x, ; EG-NEXT: 23(3.222986e-44), 0(0.000000e+00) -; EG-NEXT: CNDE_INT T3.X, PS, 0.0, PV.W, -; EG-NEXT: CNDE_INT T3.Y, PS, T3.Y, T3.Z, -; EG-NEXT: AND_INT T2.Z, T6.X, literal.x, -; EG-NEXT: NOT_INT T1.W, T6.X, -; EG-NEXT: LSHR * T3.W, T0.W, 1, -; EG-NEXT: 31(4.344025e-44), 0(0.000000e+00) -; EG-NEXT: ASHR T7.X, KC0[3].Y, literal.x, -; EG-NEXT: ADD_INT T4.Y, T1.X, literal.y, -; EG-NEXT: BIT_ALIGN_INT T3.Z, 0.0, PS, PV.W, -; EG-NEXT: LSHL T0.W, T0.W, PV.Z, -; EG-NEXT: AND_INT * T1.W, T6.X, literal.z, +; EG-NEXT: CNDE_INT T1.X, PS, 0.0, PV.W, +; EG-NEXT: CNDE_INT T6.Y, PS, T2.Z, T8.Y, +; EG-NEXT: SUB_INT T1.Z, literal.x, T0.W, +; EG-NEXT: NOT_INT T6.W, T5.Y, +; EG-NEXT: LSHR * T7.W, T3.W, 1, +; EG-NEXT: 150(2.101948e-43), 0(0.000000e+00) +; EG-NEXT: ASHR T2.X, KC0[3].Y, literal.x, +; EG-NEXT: ADD_INT T5.Y, T0.W, literal.y, +; EG-NEXT: BIT_ALIGN_INT T2.Z, 0.0, PS, PV.W, +; EG-NEXT: BIT_ALIGN_INT T0.W, 0.0, T3.W, PV.Z, +; EG-NEXT: AND_INT * T3.W, PV.Z, literal.z, ; EG-NEXT: 31(4.344025e-44), -127(nan) ; EG-NEXT: 32(4.484155e-44), 0(0.000000e+00) -; EG-NEXT: CNDE_INT T1.X, PS, PV.W, 0.0, -; EG-NEXT: CNDE_INT T5.Y, PS, PV.Z, PV.W, -; EG-NEXT: SETGT_INT T2.Z, PV.Y, literal.x, -; EG-NEXT: XOR_INT T0.W, T3.Y, PV.X, -; EG-NEXT: XOR_INT * T1.W, T3.X, PV.X, +; EG-NEXT: CNDE_INT T4.X, PS, PV.W, 0.0, +; EG-NEXT: CNDE_INT T7.Y, T5.W, PV.Z, T4.W, +; EG-NEXT: SETGT_INT T1.Z, PV.Y, literal.x, +; EG-NEXT: XOR_INT T0.W, T6.Y, PV.X, +; EG-NEXT: XOR_INT * T3.W, T1.X, PV.X, ; EG-NEXT: 23(3.222986e-44), 0(0.000000e+00) -; EG-NEXT: SUB_INT T3.X, PS, T7.X, -; EG-NEXT: SUBB_UINT T3.Y, PV.W, T7.X, -; EG-NEXT: CNDE_INT T3.Z, PV.Z, 0.0, PV.Y, -; EG-NEXT: CNDE_INT T1.W, PV.Z, T0.Z, PV.X, -; EG-NEXT: ASHR * T3.W, KC0[3].W, literal.x, +; EG-NEXT: SUB_INT T1.X, PS, T2.X, +; EG-NEXT: SUBB_UINT T6.Y, PV.W, T2.X, +; EG-NEXT: CNDE_INT T2.Z, PV.Z, 0.0, PV.Y, +; EG-NEXT: CNDE_INT T3.W, PV.Z, PV.X, T3.X, +; EG-NEXT: ASHR * T4.W, KC0[3].W, literal.x, ; EG-NEXT: 31(4.344025e-44), 0(0.000000e+00) -; EG-NEXT: XOR_INT T1.X, PV.W, PS, -; EG-NEXT: XOR_INT T5.Y, PV.Z, PS, -; EG-NEXT: SUB_INT T0.Z, PV.X, PV.Y, -; EG-NEXT: SETGT_INT T1.W, 0.0, T4.X, BS:VEC_021/SCL_122 -; EG-NEXT: CNDE_INT * T6.W, T0.Y, T5.X, 0.0, -; EG-NEXT: SETGT_INT T0.X, 0.0, T0.X, +; EG-NEXT: XOR_INT T3.X, PV.W, PS, +; EG-NEXT: XOR_INT T7.Y, PV.Z, PS, +; EG-NEXT: SUB_INT T1.Z, PV.X, PV.Y, +; EG-NEXT: SETGT_INT T3.W, 0.0, T3.Y, +; EG-NEXT: CNDE_INT * T6.W, T0.X, T0.Z, 0.0, +; EG-NEXT: SETGT_INT T1.X, 0.0, T0.Y, ; EG-NEXT: CNDE_INT T6.Y, PV.W, PV.Z, 0.0, -; EG-NEXT: SUB_INT T0.Z, T1.Y, T2.W, BS:VEC_021/SCL_122 -; EG-NEXT: SUB_INT T2.W, PV.Y, T3.W, -; EG-NEXT: SUBB_UINT * T4.W, PV.X, T3.W, -; EG-NEXT: SUB_INT T3.X, PV.W, PS, -; EG-NEXT: SETGT_INT T1.Y, 0.0, T4.Y, -; EG-NEXT: CNDE_INT T6.Z, T0.Y, PV.Z, 0.0, -; EG-NEXT: SUB_INT T0.W, T0.W, T7.X, BS:VEC_021/SCL_122 -; EG-NEXT: CNDE_INT * T4.W, PV.X, T2.X, 0.0, -; EG-NEXT: CNDE_INT T6.X, T1.W, PV.W, 0.0, -; EG-NEXT: CNDE_INT T4.Y, PV.Y, PV.X, 0.0, -; EG-NEXT: SUB_INT T0.W, T1.Z, T2.Y, -; EG-NEXT: LSHR * T2.X, KC0[2].Y, literal.x, +; EG-NEXT: SUB_INT T0.Z, T1.W, T1.Y, BS:VEC_021/SCL_122 +; EG-NEXT: SUB_INT T1.W, PV.Y, T4.W, +; EG-NEXT: SUBB_UINT * T5.W, PV.X, T4.W, +; EG-NEXT: SUB_INT T4.X, PV.W, PS, +; EG-NEXT: SETGT_INT T0.Y, 0.0, T5.Y, BS:VEC_021/SCL_122 +; EG-NEXT: CNDE_INT T6.Z, T0.X, PV.Z, 0.0, +; EG-NEXT: SUB_INT T0.W, T0.W, T2.X, +; EG-NEXT: CNDE_INT * T1.W, PV.X, T4.Y, 0.0, +; EG-NEXT: CNDE_INT T6.X, T3.W, PV.W, 0.0, +; EG-NEXT: CNDE_INT T1.Y, PV.Y, PV.X, 0.0, +; EG-NEXT: SUB_INT T0.W, T2.Y, T2.W, +; EG-NEXT: LSHR * T0.X, KC0[2].Y, literal.x, ; EG-NEXT: 2(2.802597e-45), 0(0.000000e+00) -; EG-NEXT: CNDE_INT T4.Z, T0.X, PV.W, 0.0, -; EG-NEXT: SUB_INT * T0.W, T1.X, T3.W, BS:VEC_120/SCL_212 -; EG-NEXT: CNDE_INT T4.X, T1.Y, PV.W, 0.0, +; EG-NEXT: CNDE_INT T1.Z, T1.X, PV.W, 0.0, +; EG-NEXT: SUB_INT * T0.W, T3.X, T4.W, BS:VEC_120/SCL_212 +; EG-NEXT: CNDE_INT T1.X, T0.Y, PV.W, 0.0, ; EG-NEXT: ADD_INT * T0.W, KC0[2].Y, literal.x, ; EG-NEXT: 16(2.242078e-44), 0(0.000000e+00) -; EG-NEXT: LSHR * T0.X, PV.W, literal.x, +; EG-NEXT: LSHR * T2.X, PV.W, literal.x, ; EG-NEXT: 2(2.802597e-45), 0(0.000000e+00) %conv = fptoui <4 x float> %x to <4 x i64> store <4 x i64> %conv, ptr addrspace(1) %out diff --git a/llvm/test/CodeGen/AMDGPU/llvm.exp.ll b/llvm/test/CodeGen/AMDGPU/llvm.exp.ll index 7a0450761e1f..3a867879bb80 100644 --- a/llvm/test/CodeGen/AMDGPU/llvm.exp.ll +++ b/llvm/test/CodeGen/AMDGPU/llvm.exp.ll @@ -228,23 +228,23 @@ define amdgpu_kernel void @s_exp_f32(ptr addrspace(1) %out, float %in) { ; R600-NEXT: MUL_IEEE * T2.W, PS, literal.z, ; R600-NEXT: -127(nan), 254(3.559298e-43) ; R600-NEXT: 209715200(1.972152e-31), 0(0.000000e+00) -; R600-NEXT: MUL_IEEE T3.X, T1.X, literal.x, -; R600-NEXT: MUL_IEEE T0.Y, PS, literal.y, +; R600-NEXT: MUL_IEEE T3.X, PS, literal.x, +; R600-NEXT: MUL_IEEE T0.Y, T1.X, literal.y, ; R600-NEXT: CNDE_INT T1.Z, PV.W, PV.Z, T0.Z, ; R600-NEXT: CNDE_INT T3.W, PV.Y, PV.X, T0.X, ; R600-NEXT: SETGT_INT * T4.W, T0.Z, literal.z, -; R600-NEXT: 2130706432(1.701412e+38), 209715200(1.972152e-31) +; R600-NEXT: 209715200(1.972152e-31), 2130706432(1.701412e+38) ; R600-NEXT: 127(1.779649e-43), 0(0.000000e+00) ; R600-NEXT: CNDE_INT T0.Z, PS, PV.Z, PV.W, -; R600-NEXT: CNDE_INT T0.W, T0.W, PV.Y, T2.W, -; R600-NEXT: MUL_IEEE * T2.W, PV.X, literal.x, +; R600-NEXT: MUL_IEEE T3.W, PV.Y, literal.x, +; R600-NEXT: CNDE_INT * T0.W, T0.W, PV.X, T2.W, ; R600-NEXT: 2130706432(1.701412e+38), 0(0.000000e+00) -; R600-NEXT: CNDE_INT T1.Z, T1.Y, T3.X, PS, -; R600-NEXT: CNDE_INT T0.W, T1.W, PV.W, T1.X, +; R600-NEXT: CNDE_INT T1.Z, T1.W, PS, T1.X, +; R600-NEXT: CNDE_INT T0.W, T1.Y, T0.Y, PV.W, ; R600-NEXT: LSHL * T1.W, PV.Z, literal.x, ; R600-NEXT: 23(3.222986e-44), 0(0.000000e+00) ; R600-NEXT: ADD_INT T1.W, PS, literal.x, -; R600-NEXT: CNDE_INT * T0.W, T4.W, PV.W, PV.Z, +; R600-NEXT: CNDE_INT * T0.W, T4.W, PV.Z, PV.W, ; R600-NEXT: 1065353216(1.000000e+00), 0(0.000000e+00) ; R600-NEXT: MUL_IEEE T0.W, PS, PV.W, ; R600-NEXT: SETGT * T1.W, literal.x, KC0[2].Z, @@ -258,65 +258,63 @@ define amdgpu_kernel void @s_exp_f32(ptr addrspace(1) %out, float %in) { ; ; CM-LABEL: s_exp_f32: ; CM: ; %bb.0: -; CM-NEXT: ALU 64, @4, KC0[CB0:0-32], KC1[] +; CM-NEXT: ALU 62, @4, KC0[CB0:0-32], KC1[] ; CM-NEXT: MEM_RAT_CACHELESS STORE_DWORD T0.X, T1.X ; CM-NEXT: CF_END ; CM-NEXT: PAD ; CM-NEXT: ALU clause starting at 4: ; CM-NEXT: AND_INT * T0.W, KC0[2].Z, literal.x, ; CM-NEXT: -4096(nan), 0(0.000000e+00) -; CM-NEXT: MUL_IEEE T0.Z, PV.W, literal.x, ; CM-NEXT: ADD * T1.W, KC0[2].Z, -PV.W, -; CM-NEXT: 1069064192(1.442383e+00), 0(0.000000e+00) -; CM-NEXT: MUL_IEEE T1.Z, PV.W, literal.x, -; CM-NEXT: RNDNE * T2.W, PV.Z, -; CM-NEXT: 967029397(3.122284e-04), 0(0.000000e+00) -; CM-NEXT: TRUNC T2.Z, PV.W, +; CM-NEXT: MUL_IEEE T0.Z, PV.W, literal.x, +; CM-NEXT: MUL_IEEE * T2.W, T0.W, literal.y, +; CM-NEXT: 967029397(3.122284e-04), 1069064192(1.442383e+00) +; CM-NEXT: RNDNE T1.Z, PV.W, ; CM-NEXT: MULADD_IEEE * T1.W, T1.W, literal.x, PV.Z, ; CM-NEXT: 1069064192(1.442383e+00), 0(0.000000e+00) -; CM-NEXT: MULADD_IEEE T0.Y, T0.W, literal.x, PV.W, -; CM-NEXT: ADD T0.Z, T0.Z, -T2.W, -; CM-NEXT: FLT_TO_INT * T0.W, PV.Z, +; CM-NEXT: MULADD_IEEE T0.Z, T0.W, literal.x, PV.W, +; CM-NEXT: ADD * T0.W, T2.W, -PV.Z, BS:VEC_120/SCL_212 ; CM-NEXT: 967029397(3.122284e-04), 0(0.000000e+00) -; CM-NEXT: MIN_INT T1.Z, PV.W, literal.x, -; CM-NEXT: ADD * T1.W, PV.Z, PV.Y, +; CM-NEXT: TRUNC T1.Z, T1.Z, +; CM-NEXT: ADD * T0.W, PV.W, PV.Z, +; CM-NEXT: EXP_IEEE T0.X, T0.W, +; CM-NEXT: EXP_IEEE T0.Y (MASKED), T0.W, +; CM-NEXT: EXP_IEEE T0.Z (MASKED), T0.W, +; CM-NEXT: EXP_IEEE * T0.W (MASKED), T0.W, +; CM-NEXT: FLT_TO_INT T0.Z, T1.Z, +; CM-NEXT: MUL_IEEE * T0.W, PV.X, literal.x, +; CM-NEXT: 209715200(1.972152e-31), 0(0.000000e+00) +; CM-NEXT: MUL_IEEE T0.Y, PV.W, literal.x, +; CM-NEXT: MAX_INT T1.Z, PV.Z, literal.y, +; CM-NEXT: MIN_INT * T1.W, PV.Z, literal.z, +; CM-NEXT: 209715200(1.972152e-31), -330(nan) ; CM-NEXT: 381(5.338947e-43), 0(0.000000e+00) -; CM-NEXT: EXP_IEEE T0.X, T1.W, -; CM-NEXT: EXP_IEEE T0.Y (MASKED), T1.W, -; CM-NEXT: EXP_IEEE T0.Z (MASKED), T1.W, -; CM-NEXT: EXP_IEEE * T0.W (MASKED), T1.W, -; CM-NEXT: MUL_IEEE T0.Y, PV.X, literal.x, -; CM-NEXT: ADD_INT T0.Z, T1.Z, literal.y, -; CM-NEXT: MAX_INT * T1.W, T0.W, literal.z, -; CM-NEXT: 2130706432(1.701412e+38), -254(nan) -; CM-NEXT: -330(nan), 0(0.000000e+00) -; CM-NEXT: ADD_INT T1.X, T0.W, literal.x, -; CM-NEXT: ADD_INT T1.Y, PV.W, literal.y, -; CM-NEXT: ADD_INT T1.Z, T0.W, literal.z, -; CM-NEXT: SETGT_UINT * T1.W, T0.W, literal.w, -; CM-NEXT: -127(nan), 204(2.858649e-43) +; CM-NEXT: ADD_INT T1.X, PV.W, literal.x, +; CM-NEXT: ADD_INT T1.Y, PV.Z, literal.y, +; CM-NEXT: ADD_INT T1.Z, T0.Z, literal.z, +; CM-NEXT: SETGT_UINT * T1.W, T0.Z, literal.w, +; CM-NEXT: -254(nan), 204(2.858649e-43) ; CM-NEXT: 102(1.429324e-43), -229(nan) -; CM-NEXT: SETGT_UINT T2.X, T0.W, literal.x, -; CM-NEXT: CNDE_INT T1.Y, PV.W, PV.Y, PV.Z, -; CM-NEXT: SETGT_INT T1.Z, T0.W, literal.y, -; CM-NEXT: MUL_IEEE * T2.W, T0.X, literal.z, -; CM-NEXT: 254(3.559298e-43), -127(nan) -; CM-NEXT: 209715200(1.972152e-31), 0(0.000000e+00) -; CM-NEXT: MUL_IEEE T3.X, PV.W, literal.x, -; CM-NEXT: CNDE_INT T1.Y, PV.Z, PV.Y, T0.W, -; CM-NEXT: CNDE_INT T0.Z, PV.X, T1.X, T0.Z, -; CM-NEXT: SETGT_INT * T0.W, T0.W, literal.y, -; CM-NEXT: 209715200(1.972152e-31), 127(1.779649e-43) +; CM-NEXT: ADD_INT T2.X, T0.Z, literal.x, +; CM-NEXT: SETGT_UINT T2.Y, T0.Z, literal.y, +; CM-NEXT: CNDE_INT T1.Z, PV.W, PV.Y, PV.Z, +; CM-NEXT: SETGT_INT * T2.W, T0.Z, literal.x, +; CM-NEXT: -127(nan), 254(3.559298e-43) +; CM-NEXT: MUL_IEEE T3.X, T0.X, literal.x, +; CM-NEXT: CNDE_INT T1.Y, PV.W, PV.Z, T0.Z, +; CM-NEXT: CNDE_INT T1.Z, PV.Y, PV.X, T1.X, +; CM-NEXT: SETGT_INT * T3.W, T0.Z, literal.y, +; CM-NEXT: 2130706432(1.701412e+38), 127(1.779649e-43) ; CM-NEXT: CNDE_INT T1.Y, PV.W, PV.Y, PV.Z, -; CM-NEXT: CNDE_INT T0.Z, T1.W, PV.X, T2.W, -; CM-NEXT: MUL_IEEE * T1.W, T0.Y, literal.x, +; CM-NEXT: MUL_IEEE T0.Z, PV.X, literal.x, +; CM-NEXT: CNDE_INT * T0.W, T1.W, T0.Y, T0.W, ; CM-NEXT: 2130706432(1.701412e+38), 0(0.000000e+00) -; CM-NEXT: CNDE_INT T0.Y, T2.X, T0.Y, PV.W, -; CM-NEXT: CNDE_INT T0.Z, T1.Z, PV.Z, T0.X, -; CM-NEXT: LSHL * T1.W, PV.Y, literal.x, +; CM-NEXT: CNDE_INT T0.Y, T2.W, PV.W, T0.X, +; CM-NEXT: CNDE_INT T0.Z, T2.Y, T3.X, PV.Z, +; CM-NEXT: LSHL * T0.W, PV.Y, literal.x, ; CM-NEXT: 23(3.222986e-44), 0(0.000000e+00) ; CM-NEXT: ADD_INT T1.Z, PV.W, literal.x, -; CM-NEXT: CNDE_INT * T0.W, T0.W, PV.Z, PV.Y, +; CM-NEXT: CNDE_INT * T0.W, T3.W, PV.Y, PV.Z, ; CM-NEXT: 1065353216(1.000000e+00), 0(0.000000e+00) ; CM-NEXT: MUL_IEEE T0.Z, PV.W, PV.Z, ; CM-NEXT: SETGT * T0.W, literal.x, KC0[2].Z, @@ -610,105 +608,105 @@ define amdgpu_kernel void @s_exp_v2f32(ptr addrspace(1) %out, <2 x float> %in) { ; R600-NEXT: AND_INT * T0.W, KC0[3].X, literal.x, ; R600-NEXT: -4096(nan), 0(0.000000e+00) ; R600-NEXT: ADD * T1.W, KC0[3].X, -PV.W, -; R600-NEXT: AND_INT T0.Z, KC0[2].W, literal.x, -; R600-NEXT: MUL_IEEE T2.W, PV.W, literal.y, -; R600-NEXT: MUL_IEEE * T3.W, T0.W, literal.z, -; R600-NEXT: -4096(nan), 967029397(3.122284e-04) -; R600-NEXT: 1069064192(1.442383e+00), 0(0.000000e+00) -; R600-NEXT: RNDNE T1.Z, PS, +; R600-NEXT: MUL_IEEE T2.W, PV.W, literal.x, +; R600-NEXT: MUL_IEEE * T3.W, T0.W, literal.y, +; R600-NEXT: 967029397(3.122284e-04), 1069064192(1.442383e+00) +; R600-NEXT: RNDNE T0.Z, PS, ; R600-NEXT: MULADD_IEEE T1.W, T1.W, literal.x, PV.W, -; R600-NEXT: ADD * T2.W, KC0[2].W, -PV.Z, -; R600-NEXT: 1069064192(1.442383e+00), 0(0.000000e+00) -; R600-NEXT: MUL_IEEE T0.Y, PS, literal.x, -; R600-NEXT: MUL_IEEE T2.Z, T0.Z, literal.y, +; R600-NEXT: AND_INT * T2.W, KC0[2].W, literal.y, +; R600-NEXT: 1069064192(1.442383e+00), -4096(nan) +; R600-NEXT: ADD T1.Z, KC0[2].W, -PS, ; R600-NEXT: MULADD_IEEE T0.W, T0.W, literal.x, PV.W, ; R600-NEXT: ADD * T1.W, T3.W, -PV.Z, +; R600-NEXT: 967029397(3.122284e-04), 0(0.000000e+00) +; R600-NEXT: ADD T2.Z, PS, PV.W, +; R600-NEXT: MUL_IEEE T0.W, PV.Z, literal.x, +; R600-NEXT: MUL_IEEE * T1.W, T2.W, literal.y, ; R600-NEXT: 967029397(3.122284e-04), 1069064192(1.442383e+00) -; R600-NEXT: ADD T3.Z, PS, PV.W, -; R600-NEXT: RNDNE T0.W, PV.Z, -; R600-NEXT: MULADD_IEEE * T1.W, T2.W, literal.x, PV.Y, BS:VEC_021/SCL_122 -; R600-NEXT: 1069064192(1.442383e+00), 0(0.000000e+00) -; R600-NEXT: TRUNC T0.Y, T1.Z, -; R600-NEXT: MULADD_IEEE T0.Z, T0.Z, literal.x, PS, BS:VEC_120/SCL_212 -; R600-NEXT: ADD T1.W, T2.Z, -PV.W, BS:VEC_201 +; R600-NEXT: RNDNE T0.Y, PS, +; R600-NEXT: MULADD_IEEE T1.Z, T1.Z, literal.x, PV.W, +; R600-NEXT: TRUNC T0.W, T0.Z, BS:VEC_120/SCL_212 ; R600-NEXT: EXP_IEEE * T0.X, PV.Z, -; R600-NEXT: 967029397(3.122284e-04), 0(0.000000e+00) -; R600-NEXT: ADD T0.Z, PV.W, PV.Z, -; R600-NEXT: FLT_TO_INT T1.W, PV.Y, -; R600-NEXT: MUL_IEEE * T2.W, PS, literal.x, -; R600-NEXT: 2130706432(1.701412e+38), 0(0.000000e+00) -; R600-NEXT: MUL_IEEE T1.Z, PS, literal.x, -; R600-NEXT: SETGT_UINT T3.W, PV.W, literal.y, -; R600-NEXT: EXP_IEEE * T0.Y, PV.Z, -; R600-NEXT: 2130706432(1.701412e+38), 254(3.559298e-43) -; R600-NEXT: CNDE_INT T1.X, PV.W, T2.W, PV.Z, -; R600-NEXT: MUL_IEEE T1.Y, PS, literal.x, -; R600-NEXT: MAX_INT T0.Z, T1.W, literal.y, -; R600-NEXT: MIN_INT T2.W, T1.W, literal.z, -; R600-NEXT: TRUNC * T0.W, T0.W, +; R600-NEXT: 1069064192(1.442383e+00), 0(0.000000e+00) +; R600-NEXT: FLT_TO_INT T1.Y, PV.W, +; R600-NEXT: MUL_IEEE T0.Z, PS, literal.x, +; R600-NEXT: MULADD_IEEE T0.W, T2.W, literal.y, PV.Z, +; R600-NEXT: ADD * T1.W, T1.W, -PV.Y, +; R600-NEXT: 209715200(1.972152e-31), 967029397(3.122284e-04) +; R600-NEXT: ADD T1.Z, PS, PV.W, +; R600-NEXT: MUL_IEEE T0.W, PV.Z, literal.x, +; R600-NEXT: SETGT_UINT * T1.W, PV.Y, literal.y, +; R600-NEXT: 209715200(1.972152e-31), -229(nan) +; R600-NEXT: CNDE_INT T0.Z, PS, PV.W, T0.Z, +; R600-NEXT: SETGT_INT T0.W, T1.Y, literal.x, +; R600-NEXT: EXP_IEEE * T1.X, PV.Z, +; R600-NEXT: -127(nan), 0(0.000000e+00) +; R600-NEXT: CNDE_INT T0.Z, PV.W, PV.Z, T0.X, +; R600-NEXT: MAX_INT T2.W, T1.Y, literal.x, +; R600-NEXT: MUL_IEEE * T3.W, PS, literal.y, +; R600-NEXT: -330(nan), 209715200(1.972152e-31) +; R600-NEXT: MUL_IEEE T2.X, PS, literal.x, +; R600-NEXT: ADD_INT T2.Y, PV.W, literal.y, +; R600-NEXT: ADD_INT T1.Z, T1.Y, literal.z, +; R600-NEXT: MIN_INT T2.W, T1.Y, literal.w, +; R600-NEXT: TRUNC * T4.W, T0.Y, +; R600-NEXT: 209715200(1.972152e-31), 204(2.858649e-43) +; R600-NEXT: 102(1.429324e-43), 381(5.338947e-43) +; R600-NEXT: FLT_TO_INT T3.X, PS, +; R600-NEXT: ADD_INT T0.Y, PV.W, literal.x, +; R600-NEXT: ADD_INT T2.Z, T1.Y, literal.y, +; R600-NEXT: SETGT_UINT T2.W, T1.Y, literal.z, +; R600-NEXT: CNDE_INT * T1.W, T1.W, PV.Y, PV.Z, +; R600-NEXT: -254(nan), -127(nan) +; R600-NEXT: 254(3.559298e-43), 0(0.000000e+00) +; R600-NEXT: MUL_IEEE T4.X, T1.X, literal.x, +; R600-NEXT: MUL_IEEE T2.Y, T0.X, literal.x, BS:VEC_120/SCL_212 +; R600-NEXT: CNDE_INT T1.Z, T0.W, PS, T1.Y, +; R600-NEXT: CNDE_INT T0.W, PV.W, PV.Z, PV.Y, +; R600-NEXT: MAX_INT * T1.W, PV.X, literal.y, ; R600-NEXT: 2130706432(1.701412e+38), -330(nan) -; R600-NEXT: 381(5.338947e-43), 0(0.000000e+00) -; R600-NEXT: FLT_TO_INT T2.X, PS, -; R600-NEXT: ADD_INT T2.Y, PV.W, literal.x, -; R600-NEXT: ADD_INT T0.Z, PV.Z, literal.y, -; R600-NEXT: ADD_INT T0.W, T1.W, literal.z, -; R600-NEXT: SETGT_UINT * T2.W, T1.W, literal.w, -; R600-NEXT: -254(nan), 204(2.858649e-43) -; R600-NEXT: 102(1.429324e-43), -229(nan) -; R600-NEXT: ADD_INT T3.X, T1.W, literal.x, -; R600-NEXT: CNDE_INT T3.Y, PS, PV.Z, PV.W, -; R600-NEXT: SETGT_INT T0.Z, T1.W, literal.x, -; R600-NEXT: MUL_IEEE T0.W, T0.X, literal.y, -; R600-NEXT: MUL_IEEE * T4.W, T0.Y, literal.y, -; R600-NEXT: -127(nan), 209715200(1.972152e-31) -; R600-NEXT: MUL_IEEE T4.X, PS, literal.x, -; R600-NEXT: MUL_IEEE T4.Y, PV.W, literal.x, -; R600-NEXT: CNDE_INT T1.Z, PV.Z, PV.Y, T1.W, -; R600-NEXT: CNDE_INT T3.W, T3.W, PV.X, T2.Y, -; R600-NEXT: MAX_INT * T5.W, T2.X, literal.y, -; R600-NEXT: 209715200(1.972152e-31), -330(nan) -; R600-NEXT: SETGT_INT T3.X, T1.W, literal.x, -; R600-NEXT: ADD_INT T2.Y, PS, literal.y, -; R600-NEXT: ADD_INT T2.Z, T2.X, literal.z, -; R600-NEXT: SETGT_UINT * T1.W, T2.X, literal.w, +; R600-NEXT: SETGT_INT T0.X, T1.Y, literal.x, +; R600-NEXT: ADD_INT T0.Y, PS, literal.y, +; R600-NEXT: ADD_INT T2.Z, T3.X, literal.z, +; R600-NEXT: SETGT_UINT * T1.W, T3.X, literal.w, ; R600-NEXT: 127(1.779649e-43), 204(2.858649e-43) ; R600-NEXT: 102(1.429324e-43), -229(nan) -; R600-NEXT: MIN_INT * T5.W, T2.X, literal.x, +; R600-NEXT: MIN_INT * T4.W, T3.X, literal.x, ; R600-NEXT: 381(5.338947e-43), 0(0.000000e+00) ; R600-NEXT: ADD_INT T5.X, PV.W, literal.x, -; R600-NEXT: ADD_INT T3.Y, T2.X, literal.y, -; R600-NEXT: SETGT_UINT T3.Z, T2.X, literal.z, -; R600-NEXT: CNDE_INT T5.W, T1.W, T2.Y, T2.Z, -; R600-NEXT: SETGT_INT * T6.W, T2.X, literal.y, +; R600-NEXT: ADD_INT T1.Y, T3.X, literal.y, +; R600-NEXT: SETGT_UINT T3.Z, T3.X, literal.z, +; R600-NEXT: CNDE_INT T4.W, T1.W, T0.Y, T2.Z, +; R600-NEXT: SETGT_INT * T5.W, T3.X, literal.y, ; R600-NEXT: -254(nan), -127(nan) ; R600-NEXT: 254(3.559298e-43), 0(0.000000e+00) -; R600-NEXT: CNDE_INT T6.X, PS, PV.W, T2.X, -; R600-NEXT: CNDE_INT T2.Y, PV.Z, PV.Y, PV.X, -; R600-NEXT: SETGT_INT T2.Z, T2.X, literal.x, BS:VEC_120/SCL_212 -; R600-NEXT: CNDE_INT T3.W, T3.X, T1.Z, T3.W, BS:VEC_021/SCL_122 -; R600-NEXT: CNDE_INT * T0.W, T2.W, T4.Y, T0.W, -; R600-NEXT: 127(1.779649e-43), 0(0.000000e+00) -; R600-NEXT: CNDE_INT T0.X, T0.Z, PS, T0.X, -; R600-NEXT: LSHL T3.Y, PV.W, literal.x, -; R600-NEXT: CNDE_INT T0.Z, PV.Z, PV.X, PV.Y, -; R600-NEXT: CNDE_INT T0.W, T1.W, T4.X, T4.W, -; R600-NEXT: MUL_IEEE * T1.W, T1.Y, literal.y, +; R600-NEXT: CNDE_INT T6.X, PS, PV.W, T3.X, +; R600-NEXT: CNDE_INT T0.Y, PV.Z, PV.Y, PV.X, +; R600-NEXT: SETGT_INT T2.Z, T3.X, literal.x, +; R600-NEXT: CNDE_INT T0.W, T0.X, T1.Z, T0.W, BS:VEC_120/SCL_212 +; R600-NEXT: MUL_IEEE * T4.W, T2.Y, literal.y, +; R600-NEXT: 127(1.779649e-43), 2130706432(1.701412e+38) +; R600-NEXT: CNDE_INT T3.X, T2.W, T2.Y, PS, BS:VEC_120/SCL_212 +; R600-NEXT: LSHL T1.Y, PV.W, literal.x, +; R600-NEXT: CNDE_INT T1.Z, PV.Z, PV.X, PV.Y, +; R600-NEXT: MUL_IEEE T0.W, T4.X, literal.y, +; R600-NEXT: CNDE_INT * T1.W, T1.W, T2.X, T3.W, ; R600-NEXT: 23(3.222986e-44), 2130706432(1.701412e+38) -; R600-NEXT: CNDE_INT T2.X, T3.Z, T1.Y, PS, -; R600-NEXT: CNDE_INT T0.Y, T6.W, PV.W, T0.Y, -; R600-NEXT: LSHL T0.Z, PV.Z, literal.x, +; R600-NEXT: CNDE_INT T1.X, T5.W, PS, T1.X, BS:VEC_021/SCL_122 +; R600-NEXT: CNDE_INT T0.Y, T3.Z, T4.X, PV.W, BS:VEC_201 +; R600-NEXT: LSHL T1.Z, PV.Z, literal.x, ; R600-NEXT: ADD_INT T0.W, PV.Y, literal.y, -; R600-NEXT: CNDE_INT * T1.W, T3.X, PV.X, T1.X, +; R600-NEXT: CNDE_INT * T1.W, T0.X, T0.Z, PV.X, ; R600-NEXT: 23(3.222986e-44), 1065353216(1.000000e+00) ; R600-NEXT: MUL_IEEE T1.Y, PS, PV.W, -; R600-NEXT: SETGT T1.Z, literal.x, KC0[3].X, +; R600-NEXT: SETGT T0.Z, literal.x, KC0[3].X, ; R600-NEXT: ADD_INT * T0.W, PV.Z, literal.y, ; R600-NEXT: -1026650416(-1.032789e+02), 1065353216(1.000000e+00) ; R600-NEXT: ALU clause starting at 101: -; R600-NEXT: CNDE_INT * T1.W, T2.Z, T0.Y, T2.X, +; R600-NEXT: CNDE_INT * T1.W, T2.Z, T1.X, T0.Y, ; R600-NEXT: MUL_IEEE T0.Y, PV.W, T0.W, -; R600-NEXT: SETGT T0.Z, literal.x, KC0[2].W, -; R600-NEXT: CNDE T0.W, T1.Z, T1.Y, 0.0, +; R600-NEXT: SETGT T1.Z, literal.x, KC0[2].W, +; R600-NEXT: CNDE T0.W, T0.Z, T1.Y, 0.0, ; R600-NEXT: SETGT * T1.W, KC0[3].X, literal.y, ; R600-NEXT: -1026650416(-1.032789e+02), 1118925336(8.872284e+01) ; R600-NEXT: CNDE T1.Y, PS, PV.W, literal.x, @@ -721,118 +719,116 @@ define amdgpu_kernel void @s_exp_v2f32(ptr addrspace(1) %out, <2 x float> %in) { ; ; CM-LABEL: s_exp_v2f32: ; CM: ; %bb.0: -; CM-NEXT: ALU 100, @4, KC0[CB0:0-32], KC1[] -; CM-NEXT: ALU 18, @105, KC0[CB0:0-32], KC1[] +; CM-NEXT: ALU 98, @4, KC0[CB0:0-32], KC1[] +; CM-NEXT: ALU 18, @103, KC0[CB0:0-32], KC1[] ; CM-NEXT: MEM_RAT_CACHELESS STORE_DWORD T0, T1.X ; CM-NEXT: CF_END ; CM-NEXT: ALU clause starting at 4: ; CM-NEXT: AND_INT * T0.W, KC0[2].W, literal.x, ; CM-NEXT: -4096(nan), 0(0.000000e+00) -; CM-NEXT: MUL_IEEE T0.Z, PV.W, literal.x, ; CM-NEXT: ADD * T1.W, KC0[2].W, -PV.W, +; CM-NEXT: MUL_IEEE T0.Y, PV.W, literal.x, +; CM-NEXT: MUL_IEEE T0.Z, T0.W, literal.y, +; CM-NEXT: AND_INT * T2.W, KC0[3].X, literal.z, +; CM-NEXT: 967029397(3.122284e-04), 1069064192(1.442383e+00) +; CM-NEXT: -4096(nan), 0(0.000000e+00) +; CM-NEXT: ADD T1.Y, KC0[3].X, -PV.W, +; CM-NEXT: RNDNE T1.Z, PV.Z, +; CM-NEXT: MULADD_IEEE * T1.W, T1.W, literal.x, PV.Y, ; CM-NEXT: 1069064192(1.442383e+00), 0(0.000000e+00) -; CM-NEXT: MUL_IEEE T1.Z, PV.W, literal.x, -; CM-NEXT: RNDNE * T2.W, PV.Z, -; CM-NEXT: 967029397(3.122284e-04), 0(0.000000e+00) -; CM-NEXT: TRUNC T0.Y, PV.W, -; CM-NEXT: AND_INT T2.Z, KC0[3].X, literal.x, -; CM-NEXT: MULADD_IEEE * T1.W, T1.W, literal.y, PV.Z, -; CM-NEXT: -4096(nan), 1069064192(1.442383e+00) ; CM-NEXT: MULADD_IEEE T0.X, T0.W, literal.x, PV.W, -; CM-NEXT: MUL_IEEE T1.Y, PV.Z, literal.y, -; CM-NEXT: FLT_TO_INT T1.Z, PV.Y, -; CM-NEXT: ADD * T0.W, KC0[3].X, -PV.Z, +; CM-NEXT: ADD T0.Y, T0.Z, -PV.Z, +; CM-NEXT: MUL_IEEE T0.Z, PV.Y, literal.x, +; CM-NEXT: MUL_IEEE * T0.W, T2.W, literal.y, BS:VEC_120/SCL_212 ; CM-NEXT: 967029397(3.122284e-04), 1069064192(1.442383e+00) -; CM-NEXT: ADD T1.X, T0.Z, -T2.W, -; CM-NEXT: MUL_IEEE T0.Y, PV.W, literal.x, -; CM-NEXT: MAX_INT T0.Z, PV.Z, literal.y, -; CM-NEXT: RNDNE * T1.W, PV.Y, -; CM-NEXT: 967029397(3.122284e-04), -330(nan) -; CM-NEXT: TRUNC T2.X, PV.W, -; CM-NEXT: ADD_INT T2.Y, PV.Z, literal.x, -; CM-NEXT: MULADD_IEEE T0.Z, T0.W, literal.y, PV.Y, -; CM-NEXT: ADD * T0.W, PV.X, T0.X, -; CM-NEXT: 204(2.858649e-43), 1069064192(1.442383e+00) -; CM-NEXT: EXP_IEEE T0.X, T0.W, -; CM-NEXT: EXP_IEEE T0.Y (MASKED), T0.W, -; CM-NEXT: EXP_IEEE T0.Z (MASKED), T0.W, -; CM-NEXT: EXP_IEEE * T0.W (MASKED), T0.W, -; CM-NEXT: ADD_INT T1.X, T1.Z, literal.x, -; CM-NEXT: MULADD_IEEE T0.Y, T2.Z, literal.y, T0.Z, BS:VEC_102/SCL_221 -; CM-NEXT: ADD T0.Z, T1.Y, -T1.W, -; CM-NEXT: MUL_IEEE * T0.W, PV.X, literal.z, -; CM-NEXT: 102(1.429324e-43), 967029397(3.122284e-04) -; CM-NEXT: 2130706432(1.701412e+38), 0(0.000000e+00) -; CM-NEXT: SETGT_UINT T3.X, T1.Z, literal.x, -; CM-NEXT: MUL_IEEE T1.Y, PV.W, literal.y, -; CM-NEXT: SETGT_UINT T2.Z, T1.Z, literal.z, -; CM-NEXT: ADD * T1.W, PV.Z, PV.Y, -; CM-NEXT: -229(nan), 2130706432(1.701412e+38) -; CM-NEXT: 254(3.559298e-43), 0(0.000000e+00) +; CM-NEXT: TRUNC T1.X, T1.Z, +; CM-NEXT: RNDNE T2.Y, PV.W, +; CM-NEXT: MULADD_IEEE T0.Z, T1.Y, literal.x, PV.Z, +; CM-NEXT: ADD * T1.W, PV.Y, PV.X, +; CM-NEXT: 1069064192(1.442383e+00), 0(0.000000e+00) +; CM-NEXT: EXP_IEEE T0.X, T1.W, +; CM-NEXT: EXP_IEEE T0.Y (MASKED), T1.W, +; CM-NEXT: EXP_IEEE T0.Z (MASKED), T1.W, +; CM-NEXT: EXP_IEEE * T0.W (MASKED), T1.W, +; CM-NEXT: MULADD_IEEE T2.X, T2.W, literal.x, T0.Z, +; CM-NEXT: ADD T0.Y, T0.W, -T2.Y, BS:VEC_120/SCL_212 +; CM-NEXT: FLT_TO_INT T0.Z, T1.X, +; CM-NEXT: MUL_IEEE * T0.W, PV.X, literal.y, +; CM-NEXT: 967029397(3.122284e-04), 209715200(1.972152e-31) +; CM-NEXT: MUL_IEEE T1.X, PV.W, literal.x, +; CM-NEXT: SETGT_UINT T1.Y, PV.Z, literal.y, +; CM-NEXT: TRUNC T1.Z, T2.Y, +; CM-NEXT: ADD * T1.W, PV.Y, PV.X, +; CM-NEXT: 209715200(1.972152e-31), -229(nan) ; CM-NEXT: EXP_IEEE T0.X (MASKED), T1.W, ; CM-NEXT: EXP_IEEE T0.Y, T1.W, ; CM-NEXT: EXP_IEEE T0.Z (MASKED), T1.W, ; CM-NEXT: EXP_IEEE * T0.W (MASKED), T1.W, -; CM-NEXT: CNDE_INT T4.X, T2.Z, T0.W, T1.Y, -; CM-NEXT: CNDE_INT T1.Y, T3.X, T2.Y, T1.X, -; CM-NEXT: FLT_TO_INT T0.Z, T2.X, BS:VEC_120/SCL_212 -; CM-NEXT: MUL_IEEE * T0.W, PV.Y, literal.x, -; CM-NEXT: 2130706432(1.701412e+38), 0(0.000000e+00) -; CM-NEXT: SETGT_INT T1.X, T1.Z, literal.x, -; CM-NEXT: MUL_IEEE T2.Y, T0.X, literal.y, -; CM-NEXT: MUL_IEEE T3.Z, PV.W, literal.z, -; CM-NEXT: SETGT_UINT * T1.W, PV.Z, literal.w, -; CM-NEXT: -127(nan), 209715200(1.972152e-31) -; CM-NEXT: 2130706432(1.701412e+38), 254(3.559298e-43) -; CM-NEXT: CNDE_INT T2.X, PV.W, T0.W, PV.Z, +; CM-NEXT: FLT_TO_INT T2.X, T1.Z, +; CM-NEXT: MUL_IEEE T2.Y, PV.Y, literal.x, +; CM-NEXT: CNDE_INT T1.Z, T1.Y, T1.X, T0.W, +; CM-NEXT: SETGT_INT * T0.W, T0.Z, literal.y, BS:VEC_120/SCL_212 +; CM-NEXT: 209715200(1.972152e-31), -127(nan) +; CM-NEXT: CNDE_INT T1.X, PV.W, PV.Z, T0.X, ; CM-NEXT: MUL_IEEE T3.Y, PV.Y, literal.x, -; CM-NEXT: CNDE_INT T3.Z, PV.X, T1.Y, T1.Z, -; CM-NEXT: MAX_INT * T0.W, T0.Z, literal.y, -; CM-NEXT: 209715200(1.972152e-31), -330(nan) -; CM-NEXT: ADD_INT T5.X, PV.W, literal.x, -; CM-NEXT: ADD_INT T1.Y, T0.Z, literal.y, -; CM-NEXT: SETGT_UINT T4.Z, T0.Z, literal.z, -; CM-NEXT: MUL_IEEE * T0.W, T0.Y, literal.w, +; CM-NEXT: SETGT_UINT T1.Z, PV.X, literal.y, +; CM-NEXT: MAX_INT * T1.W, T0.Z, literal.z, +; CM-NEXT: 209715200(1.972152e-31), -229(nan) +; CM-NEXT: -330(nan), 0(0.000000e+00) +; CM-NEXT: ADD_INT T3.X, PV.W, literal.x, +; CM-NEXT: ADD_INT T4.Y, T0.Z, literal.y, +; CM-NEXT: CNDE_INT T2.Z, PV.Z, PV.Y, T2.Y, +; CM-NEXT: SETGT_INT * T1.W, T2.X, literal.z, ; CM-NEXT: 204(2.858649e-43), 102(1.429324e-43) -; CM-NEXT: -229(nan), 209715200(1.972152e-31) -; CM-NEXT: MUL_IEEE T6.X, PV.W, literal.x, -; CM-NEXT: MIN_INT T4.Y, T0.Z, literal.y, -; CM-NEXT: CNDE_INT T5.Z, PV.Z, PV.X, PV.Y, -; CM-NEXT: SETGT_INT * T2.W, T0.Z, literal.z, -; CM-NEXT: 209715200(1.972152e-31), 381(5.338947e-43) -; CM-NEXT: -127(nan), 0(0.000000e+00) -; CM-NEXT: CNDE_INT T5.X, PV.W, PV.Z, T0.Z, -; CM-NEXT: MIN_INT T1.Y, T1.Z, literal.x, -; CM-NEXT: ADD_INT T5.Z, PV.Y, literal.y, -; CM-NEXT: ADD_INT * T3.W, T0.Z, literal.z, BS:VEC_120/SCL_212 -; CM-NEXT: 381(5.338947e-43), -254(nan) ; CM-NEXT: -127(nan), 0(0.000000e+00) -; CM-NEXT: CNDE_INT T7.X, T1.W, PV.W, PV.Z, -; CM-NEXT: SETGT_INT T4.Y, T0.Z, literal.x, -; CM-NEXT: ADD_INT T0.Z, PV.Y, literal.y, -; CM-NEXT: ADD_INT * T1.W, T1.Z, literal.z, BS:VEC_120/SCL_212 +; CM-NEXT: CNDE_INT T4.X, PV.W, PV.Z, T0.Y, +; CM-NEXT: MUL_IEEE T2.Y, T0.X, literal.x, +; CM-NEXT: MAX_INT T2.Z, T2.X, literal.y, BS:VEC_120/SCL_212 +; CM-NEXT: CNDE_INT * T2.W, T1.Y, PV.X, PV.Y, +; CM-NEXT: 2130706432(1.701412e+38), -330(nan) +; CM-NEXT: CNDE_INT T0.X, T0.W, PV.W, T0.Z, +; CM-NEXT: ADD_INT T1.Y, PV.Z, literal.x, +; CM-NEXT: ADD_INT T2.Z, T2.X, literal.y, +; CM-NEXT: MIN_INT * T0.W, T2.X, literal.z, +; CM-NEXT: 204(2.858649e-43), 102(1.429324e-43) +; CM-NEXT: 381(5.338947e-43), 0(0.000000e+00) +; CM-NEXT: ADD_INT T3.X, PV.W, literal.x, +; CM-NEXT: ADD_INT T3.Y, T2.X, literal.y, +; CM-NEXT: SETGT_UINT T3.Z, T2.X, literal.z, +; CM-NEXT: CNDE_INT * T0.W, T1.Z, PV.Y, PV.Z, +; CM-NEXT: -254(nan), -127(nan) +; CM-NEXT: 254(3.559298e-43), 0(0.000000e+00) +; CM-NEXT: MUL_IEEE T5.X, T0.Y, literal.x, +; CM-NEXT: CNDE_INT T0.Y, T1.W, PV.W, T2.X, +; CM-NEXT: CNDE_INT T1.Z, PV.Z, PV.Y, PV.X, +; CM-NEXT: MIN_INT * T0.W, T0.Z, literal.y, +; CM-NEXT: 2130706432(1.701412e+38), 381(5.338947e-43) +; CM-NEXT: SETGT_INT T2.X, T2.X, literal.x, +; CM-NEXT: ADD_INT T1.Y, PV.W, literal.y, +; CM-NEXT: ADD_INT T2.Z, T0.Z, literal.z, +; CM-NEXT: SETGT_UINT * T0.W, T0.Z, literal.w, ; CM-NEXT: 127(1.779649e-43), -254(nan) -; CM-NEXT: -127(nan), 0(0.000000e+00) -; CM-NEXT: CNDE_INT T8.X, T2.Z, PV.W, PV.Z, -; CM-NEXT: SETGT_INT T1.Y, T1.Z, literal.x, BS:VEC_120/SCL_212 -; CM-NEXT: CNDE_INT T0.Z, PV.Y, T5.X, PV.X, -; CM-NEXT: CNDE_INT * T0.W, T4.Z, T6.X, T0.W, BS:VEC_201 -; CM-NEXT: 127(1.779649e-43), 0(0.000000e+00) -; CM-NEXT: CNDE_INT T5.X, T2.W, PV.W, T0.Y, +; CM-NEXT: -127(nan), 254(3.559298e-43) +; CM-NEXT: CNDE_INT T3.X, PV.W, PV.Z, PV.Y, +; CM-NEXT: SETGT_INT T1.Y, T0.Z, literal.x, +; CM-NEXT: CNDE_INT T0.Z, PV.X, T0.Y, T1.Z, +; CM-NEXT: MUL_IEEE * T1.W, T5.X, literal.y, +; CM-NEXT: 127(1.779649e-43), 2130706432(1.701412e+38) +; CM-NEXT: CNDE_INT T5.X, T3.Z, T5.X, PV.W, ; CM-NEXT: LSHL T0.Y, PV.Z, literal.x, -; CM-NEXT: CNDE_INT T0.Z, PV.Y, T3.Z, PV.X, -; CM-NEXT: CNDE_INT * T0.W, T3.X, T3.Y, T2.Y, BS:VEC_201 -; CM-NEXT: 23(3.222986e-44), 0(0.000000e+00) -; CM-NEXT: CNDE_INT T0.X, T1.X, PV.W, T0.X, +; CM-NEXT: CNDE_INT T0.Z, PV.Y, T0.X, PV.X, BS:VEC_021/SCL_122 +; CM-NEXT: MUL_IEEE * T1.W, T2.Y, literal.y, +; CM-NEXT: 23(3.222986e-44), 2130706432(1.701412e+38) +; CM-NEXT: CNDE_INT T0.X, T0.W, T2.Y, PV.W, ; CM-NEXT: LSHL T2.Y, PV.Z, literal.x, ; CM-NEXT: ADD_INT * T0.Z, PV.Y, literal.y, ; CM-NEXT: 23(3.222986e-44), 1065353216(1.000000e+00) -; CM-NEXT: ALU clause starting at 105: -; CM-NEXT: CNDE_INT * T0.W, T4.Y, T5.X, T2.X, -; CM-NEXT: MUL_IEEE T1.X, PV.W, T0.Z, +; CM-NEXT: ALU clause starting at 103: +; CM-NEXT: CNDE_INT * T0.W, T2.X, T4.X, T5.X, +; CM-NEXT: MUL_IEEE T2.X, PV.W, T0.Z, ; CM-NEXT: SETGT T0.Y, literal.x, KC0[3].X, ; CM-NEXT: ADD_INT T0.Z, T2.Y, literal.y, -; CM-NEXT: CNDE_INT * T0.W, T1.Y, T0.X, T4.X, BS:VEC_120/SCL_212 +; CM-NEXT: CNDE_INT * T0.W, T1.Y, T1.X, T0.X, BS:VEC_120/SCL_212 ; CM-NEXT: -1026650416(-1.032789e+02), 1065353216(1.000000e+00) ; CM-NEXT: MUL_IEEE T0.X, PV.W, PV.Z, ; CM-NEXT: SETGT T1.Y, literal.x, KC0[2].W, @@ -1215,8 +1211,8 @@ define amdgpu_kernel void @s_exp_v3f32(ptr addrspace(1) %out, <3 x float> %in) { ; ; R600-LABEL: s_exp_v3f32: ; R600: ; %bb.0: -; R600-NEXT: ALU 100, @6, KC0[CB0:0-32], KC1[] -; R600-NEXT: ALU 69, @107, KC0[CB0:0-32], KC1[] +; R600-NEXT: ALU 99, @6, KC0[CB0:0-32], KC1[] +; R600-NEXT: ALU 69, @106, KC0[CB0:0-32], KC1[] ; R600-NEXT: MEM_RAT_CACHELESS STORE_RAW T2.X, T3.X, 0 ; R600-NEXT: MEM_RAT_CACHELESS STORE_RAW T0.XY, T1.X, 1 ; R600-NEXT: CF_END @@ -1224,69 +1220,68 @@ define amdgpu_kernel void @s_exp_v3f32(ptr addrspace(1) %out, <3 x float> %in) { ; R600-NEXT: ALU clause starting at 6: ; R600-NEXT: AND_INT * T0.W, KC0[3].Y, literal.x, ; R600-NEXT: -4096(nan), 0(0.000000e+00) -; R600-NEXT: ADD T1.W, KC0[3].Y, -PV.W, -; R600-NEXT: MUL_IEEE * T2.W, PV.W, literal.x, +; R600-NEXT: MUL_IEEE T1.W, PV.W, literal.x, +; R600-NEXT: ADD * T2.W, KC0[3].Y, -PV.W, ; R600-NEXT: 1069064192(1.442383e+00), 0(0.000000e+00) -; R600-NEXT: RNDNE T3.W, PS, -; R600-NEXT: MUL_IEEE * T4.W, PV.W, literal.x, +; R600-NEXT: RNDNE * T3.W, PV.W, +; R600-NEXT: TRUNC T4.W, PV.W, +; R600-NEXT: MUL_IEEE * T5.W, T2.W, literal.x, ; R600-NEXT: 967029397(3.122284e-04), 0(0.000000e+00) -; R600-NEXT: MULADD_IEEE T1.W, T1.W, literal.x, PS, -; R600-NEXT: TRUNC * T4.W, PV.W, +; R600-NEXT: MULADD_IEEE T2.W, T2.W, literal.x, PS, +; R600-NEXT: FLT_TO_INT * T4.W, PV.W, ; R600-NEXT: 1069064192(1.442383e+00), 0(0.000000e+00) -; R600-NEXT: FLT_TO_INT T0.Z, PS, -; R600-NEXT: MULADD_IEEE T0.W, T0.W, literal.x, PV.W, -; R600-NEXT: ADD * T1.W, T2.W, -T3.W, -; R600-NEXT: 967029397(3.122284e-04), 0(0.000000e+00) -; R600-NEXT: ADD T0.W, PS, PV.W, -; R600-NEXT: MAX_INT * T1.W, PV.Z, literal.x, -; R600-NEXT: -330(nan), 0(0.000000e+00) -; R600-NEXT: ADD_INT T0.Y, PS, literal.x, -; R600-NEXT: ADD_INT T1.Z, T0.Z, literal.y, -; R600-NEXT: SETGT_UINT T1.W, T0.Z, literal.z, -; R600-NEXT: EXP_IEEE * T0.X, PV.W, +; R600-NEXT: MAX_INT T0.Z, PS, literal.x, +; R600-NEXT: MULADD_IEEE T0.W, T0.W, literal.y, PV.W, +; R600-NEXT: ADD * T1.W, T1.W, -T3.W, +; R600-NEXT: -330(nan), 967029397(3.122284e-04) +; R600-NEXT: ADD T0.Y, PS, PV.W, +; R600-NEXT: ADD_INT T0.Z, PV.Z, literal.x, +; R600-NEXT: ADD_INT T0.W, T4.W, literal.y, +; R600-NEXT: SETGT_UINT * T1.W, T4.W, literal.z, ; R600-NEXT: 204(2.858649e-43), 102(1.429324e-43) ; R600-NEXT: -229(nan), 0(0.000000e+00) -; R600-NEXT: CNDE_INT T1.Z, PV.W, PV.Y, PV.Z, -; R600-NEXT: SETGT_INT T0.W, T0.Z, literal.x, -; R600-NEXT: MUL_IEEE * T2.W, PS, literal.y, -; R600-NEXT: -127(nan), 209715200(1.972152e-31) -; R600-NEXT: MUL_IEEE T0.Y, PS, literal.x, -; R600-NEXT: CNDE_INT T1.Z, PV.W, PV.Z, T0.Z, -; R600-NEXT: MIN_INT T3.W, T0.Z, literal.y, -; R600-NEXT: AND_INT * T4.W, KC0[3].W, literal.z, -; R600-NEXT: 209715200(1.972152e-31), 381(5.338947e-43) -; R600-NEXT: -4096(nan), 0(0.000000e+00) -; R600-NEXT: MUL_IEEE T1.X, T0.X, literal.x, -; R600-NEXT: ADD T1.Y, KC0[3].W, -PS, -; R600-NEXT: ADD_INT T2.Z, PV.W, literal.y, -; R600-NEXT: ADD_INT T3.W, T0.Z, literal.z, -; R600-NEXT: SETGT_UINT * T5.W, T0.Z, literal.w, -; R600-NEXT: 2130706432(1.701412e+38), -254(nan) +; R600-NEXT: CNDE_INT T0.Z, PS, PV.Z, PV.W, +; R600-NEXT: SETGT_INT T0.W, T4.W, literal.x, +; R600-NEXT: EXP_IEEE * T0.X, PV.Y, +; R600-NEXT: -127(nan), 0(0.000000e+00) +; R600-NEXT: MUL_IEEE T1.X, PS, literal.x, +; R600-NEXT: CNDE_INT T0.Y, PV.W, PV.Z, T4.W, +; R600-NEXT: MIN_INT T0.Z, T4.W, literal.y, +; R600-NEXT: AND_INT T2.W, KC0[3].W, literal.z, +; R600-NEXT: MUL_IEEE * T3.W, PS, literal.w, +; R600-NEXT: 2130706432(1.701412e+38), 381(5.338947e-43) +; R600-NEXT: -4096(nan), 209715200(1.972152e-31) +; R600-NEXT: MUL_IEEE T2.X, PS, literal.x, +; R600-NEXT: ADD T1.Y, KC0[3].W, -PV.W, +; R600-NEXT: ADD_INT T0.Z, PV.Z, literal.y, +; R600-NEXT: ADD_INT T5.W, T4.W, literal.z, +; R600-NEXT: SETGT_UINT * T6.W, T4.W, literal.w, +; R600-NEXT: 209715200(1.972152e-31), -254(nan) ; R600-NEXT: -127(nan), 254(3.559298e-43) -; R600-NEXT: CNDE_INT T2.X, PS, PV.W, PV.Z, -; R600-NEXT: SETGT_INT T2.Y, T0.Z, literal.x, +; R600-NEXT: CNDE_INT T3.X, PS, PV.W, PV.Z, +; R600-NEXT: SETGT_INT T2.Y, T4.W, literal.x, ; R600-NEXT: MUL_IEEE T0.Z, PV.Y, literal.y, -; R600-NEXT: MUL_IEEE T3.W, T4.W, literal.z, -; R600-NEXT: MUL_IEEE * T6.W, PV.X, literal.w, +; R600-NEXT: MUL_IEEE * T4.W, T2.W, literal.z, BS:VEC_120/SCL_212 ; R600-NEXT: 127(1.779649e-43), 967029397(3.122284e-04) -; R600-NEXT: 1069064192(1.442383e+00), 2130706432(1.701412e+38) -; R600-NEXT: CNDE_INT T1.X, T5.W, T1.X, PS, BS:VEC_120/SCL_212 -; R600-NEXT: RNDNE T3.Y, PV.W, -; R600-NEXT: MULADD_IEEE T0.Z, T1.Y, literal.x, PV.Z, -; R600-NEXT: CNDE_INT T5.W, PV.Y, T1.Z, PV.X, -; R600-NEXT: CNDE_INT * T1.W, T1.W, T0.Y, T2.W, ; R600-NEXT: 1069064192(1.442383e+00), 0(0.000000e+00) -; R600-NEXT: CNDE_INT T0.X, T0.W, PS, T0.X, +; R600-NEXT: CNDE_INT * T1.W, T1.W, T2.X, T3.W, +; R600-NEXT: CNDE_INT T0.X, T0.W, PV.W, T0.X, BS:VEC_021/SCL_122 +; R600-NEXT: RNDNE T3.Y, T4.W, BS:VEC_120/SCL_212 +; R600-NEXT: MULADD_IEEE T0.Z, T1.Y, literal.x, T0.Z, +; R600-NEXT: CNDE_INT T0.W, T2.Y, T0.Y, T3.X, BS:VEC_120/SCL_212 +; R600-NEXT: MUL_IEEE * T1.W, T1.X, literal.y, +; R600-NEXT: 1069064192(1.442383e+00), 2130706432(1.701412e+38) +; R600-NEXT: CNDE_INT T1.X, T6.W, T1.X, PS, ; R600-NEXT: LSHL T0.Y, PV.W, literal.x, ; R600-NEXT: AND_INT T1.Z, KC0[3].Z, literal.y, -; R600-NEXT: MULADD_IEEE T0.W, T4.W, literal.z, PV.Z, BS:VEC_120/SCL_212 -; R600-NEXT: ADD * T1.W, T3.W, -PV.Y, +; R600-NEXT: MULADD_IEEE T0.W, T2.W, literal.z, PV.Z, BS:VEC_120/SCL_212 +; R600-NEXT: ADD * T1.W, T4.W, -PV.Y, ; R600-NEXT: 23(3.222986e-44), -4096(nan) ; R600-NEXT: 967029397(3.122284e-04), 0(0.000000e+00) ; R600-NEXT: ADD T1.Y, PS, PV.W, ; R600-NEXT: MUL_IEEE T0.Z, PV.Z, literal.x, ; R600-NEXT: ADD_INT T0.W, PV.Y, literal.y, -; R600-NEXT: CNDE_INT * T1.W, T2.Y, PV.X, T1.X, +; R600-NEXT: CNDE_INT * T1.W, T2.Y, T0.X, PV.X, ; R600-NEXT: 1069064192(1.442383e+00), 1065353216(1.000000e+00) ; R600-NEXT: MUL_IEEE T0.X, PS, PV.W, ; R600-NEXT: ADD T0.Y, KC0[3].Z, -T1.Z, @@ -1300,12 +1295,12 @@ define amdgpu_kernel void @s_exp_v3f32(ptr addrspace(1) %out, <3 x float> %in) { ; R600-NEXT: MUL_IEEE * T1.W, PS, literal.z, ; R600-NEXT: -1026650416(-1.032789e+02), 967029397(3.122284e-04) ; R600-NEXT: 209715200(1.972152e-31), 0(0.000000e+00) -; R600-NEXT: MUL_IEEE T3.X, T1.X, literal.x, -; R600-NEXT: MUL_IEEE T2.Y, PS, literal.y, +; R600-NEXT: MUL_IEEE T3.X, PS, literal.x, +; R600-NEXT: MUL_IEEE T2.Y, T1.X, literal.y, ; R600-NEXT: MULADD_IEEE T4.Z, T0.Y, literal.z, PV.W, ; R600-NEXT: FLT_TO_INT T0.W, PV.Z, ; R600-NEXT: MIN_INT * T2.W, PV.Y, literal.w, -; R600-NEXT: 2130706432(1.701412e+38), 209715200(1.972152e-31) +; R600-NEXT: 209715200(1.972152e-31), 2130706432(1.701412e+38) ; R600-NEXT: 1069064192(1.442383e+00), 381(5.338947e-43) ; R600-NEXT: ADD_INT T4.X, PS, literal.x, ; R600-NEXT: MAX_INT T0.Y, PV.W, literal.y, @@ -1323,7 +1318,7 @@ define amdgpu_kernel void @s_exp_v3f32(ptr addrspace(1) %out, <3 x float> %in) { ; R600-NEXT: 102(1.429324e-43), -229(nan) ; R600-NEXT: ADD_INT * T6.X, T0.W, literal.x, ; R600-NEXT: -127(nan), 0(0.000000e+00) -; R600-NEXT: ALU clause starting at 107: +; R600-NEXT: ALU clause starting at 106: ; R600-NEXT: SETGT_UINT T0.Y, T0.W, literal.x, ; R600-NEXT: CNDE_INT T0.Z, T3.W, T0.Z, T2.W, BS:VEC_102/SCL_221 ; R600-NEXT: SETGT_INT T2.W, T0.W, literal.y, @@ -1339,25 +1334,25 @@ define amdgpu_kernel void @s_exp_v3f32(ptr addrspace(1) %out, <3 x float> %in) { ; R600-NEXT: SETGT_UINT T5.X, T1.Y, literal.x, ; R600-NEXT: CNDE_INT T4.Y, PS, PV.Z, PV.W, ; R600-NEXT: MAX_INT T0.Z, T1.Y, literal.y, -; R600-NEXT: MUL_IEEE T4.W, T1.Z, literal.z, -; R600-NEXT: MUL_IEEE * T5.W, PV.Y, literal.w, +; R600-NEXT: MUL_IEEE T4.W, PV.Y, literal.z, +; R600-NEXT: MUL_IEEE * T5.W, T1.Z, literal.w, ; R600-NEXT: 254(3.559298e-43), -330(nan) -; R600-NEXT: 2130706432(1.701412e+38), 209715200(1.972152e-31) -; R600-NEXT: CNDE_INT T6.X, T3.W, PS, T3.Y, BS:VEC_021/SCL_122 -; R600-NEXT: MUL_IEEE T3.Y, PV.W, literal.x, +; R600-NEXT: 209715200(1.972152e-31), 2130706432(1.701412e+38) +; R600-NEXT: MUL_IEEE T6.X, PS, literal.x, +; R600-NEXT: CNDE_INT T3.Y, T3.W, PV.W, T3.Y, BS:VEC_021/SCL_122 ; R600-NEXT: ADD_INT T0.Z, PV.Z, literal.y, ; R600-NEXT: ADD_INT T3.W, T1.Y, literal.z, -; R600-NEXT: SETGT_UINT * T5.W, T1.Y, literal.w, +; R600-NEXT: SETGT_UINT * T4.W, T1.Y, literal.w, ; R600-NEXT: 2130706432(1.701412e+38), 204(2.858649e-43) ; R600-NEXT: 102(1.429324e-43), -229(nan) ; R600-NEXT: CNDE_INT T8.X, PS, PV.Z, PV.W, ; R600-NEXT: SETGT_INT T5.Y, T1.Y, literal.x, -; R600-NEXT: CNDE_INT T0.Z, T0.Y, T4.W, PV.Y, BS:VEC_120/SCL_212 -; R600-NEXT: CNDE_INT T2.W, T2.W, PV.X, T1.Z, +; R600-NEXT: CNDE_INT T0.Z, T2.W, PV.Y, T1.Z, +; R600-NEXT: CNDE_INT T2.W, T0.Y, T5.W, PV.X, BS:VEC_120/SCL_212 ; R600-NEXT: LSHL * T3.W, T4.Y, literal.y, ; R600-NEXT: -127(nan), 23(3.222986e-44) ; R600-NEXT: ADD_INT T6.X, PS, literal.x, -; R600-NEXT: CNDE_INT T0.Y, T0.W, PV.W, PV.Z, +; R600-NEXT: CNDE_INT T0.Y, T0.W, PV.Z, PV.W, ; R600-NEXT: CNDE_INT T0.Z, PV.Y, PV.X, T1.Y, ; R600-NEXT: CNDE_INT T0.W, T5.X, T7.X, T4.X, ; R600-NEXT: SETGT_INT * T2.W, T1.Y, literal.y, @@ -1365,18 +1360,18 @@ define amdgpu_kernel void @s_exp_v3f32(ptr addrspace(1) %out, <3 x float> %in) { ; R600-NEXT: CNDE_INT T4.X, PS, PV.Z, PV.W, ; R600-NEXT: MUL_IEEE T0.Y, PV.Y, PV.X, ; R600-NEXT: SETGT T0.Z, literal.x, KC0[3].Z, -; R600-NEXT: CNDE_INT T0.W, T5.W, T2.Y, T1.W, -; R600-NEXT: MUL_IEEE * T1.W, T3.X, literal.y, +; R600-NEXT: MUL_IEEE T0.W, T2.Y, literal.y, +; R600-NEXT: CNDE_INT * T1.W, T4.W, T3.X, T1.W, ; R600-NEXT: -1026650416(-1.032789e+02), 2130706432(1.701412e+38) -; R600-NEXT: CNDE_INT T3.X, T5.X, T3.X, PS, -; R600-NEXT: CNDE_INT T1.Y, T5.Y, PV.W, T1.X, +; R600-NEXT: CNDE_INT T1.X, T5.Y, PS, T1.X, +; R600-NEXT: CNDE_INT T1.Y, T5.X, T2.Y, PV.W, ; R600-NEXT: CNDE T0.Z, PV.Z, PV.Y, 0.0, ; R600-NEXT: SETGT T0.W, KC0[3].Z, literal.x, ; R600-NEXT: LSHL * T1.W, PV.X, literal.y, ; R600-NEXT: 1118925336(8.872284e+01), 23(3.222986e-44) -; R600-NEXT: ADD_INT T1.X, PS, literal.x, +; R600-NEXT: ADD_INT T3.X, PS, literal.x, ; R600-NEXT: CNDE T0.Y, PV.W, PV.Z, literal.y, -; R600-NEXT: CNDE_INT T0.Z, T2.W, PV.Y, PV.X, +; R600-NEXT: CNDE_INT T0.Z, T2.W, PV.X, PV.Y, ; R600-NEXT: CNDE T0.W, T2.X, T0.X, 0.0, ; R600-NEXT: SETGT * T1.W, KC0[3].Y, literal.z, ; R600-NEXT: 1065353216(1.000000e+00), 2139095040(INF) @@ -1397,197 +1392,193 @@ define amdgpu_kernel void @s_exp_v3f32(ptr addrspace(1) %out, <3 x float> %in) { ; ; CM-LABEL: s_exp_v3f32: ; CM: ; %bb.0: -; CM-NEXT: ALU 102, @6, KC0[CB0:0-32], KC1[] -; CM-NEXT: ALU 80, @109, KC0[CB0:0-32], KC1[] -; CM-NEXT: MEM_RAT_CACHELESS STORE_DWORD T1, T3.X -; CM-NEXT: MEM_RAT_CACHELESS STORE_DWORD T2.X, T0.X +; CM-NEXT: ALU 101, @6, KC0[CB0:0-32], KC1[] +; CM-NEXT: ALU 77, @108, KC0[CB0:0-32], KC1[] +; CM-NEXT: MEM_RAT_CACHELESS STORE_DWORD T0, T1.X +; CM-NEXT: MEM_RAT_CACHELESS STORE_DWORD T2.X, T3.X ; CM-NEXT: CF_END ; CM-NEXT: PAD ; CM-NEXT: ALU clause starting at 6: ; CM-NEXT: AND_INT * T0.W, KC0[3].Y, literal.x, ; CM-NEXT: -4096(nan), 0(0.000000e+00) -; CM-NEXT: MUL_IEEE T0.Z, PV.W, literal.x, ; CM-NEXT: ADD * T1.W, KC0[3].Y, -PV.W, -; CM-NEXT: 1069064192(1.442383e+00), 0(0.000000e+00) -; CM-NEXT: MUL_IEEE T1.Z, PV.W, literal.x, -; CM-NEXT: RNDNE * T2.W, PV.Z, -; CM-NEXT: 967029397(3.122284e-04), 0(0.000000e+00) -; CM-NEXT: TRUNC T2.Z, PV.W, +; CM-NEXT: MUL_IEEE T0.Z, PV.W, literal.x, +; CM-NEXT: MUL_IEEE * T2.W, T0.W, literal.y, +; CM-NEXT: 967029397(3.122284e-04), 1069064192(1.442383e+00) +; CM-NEXT: RNDNE T1.Z, PV.W, ; CM-NEXT: MULADD_IEEE * T1.W, T1.W, literal.x, PV.Z, ; CM-NEXT: 1069064192(1.442383e+00), 0(0.000000e+00) -; CM-NEXT: MULADD_IEEE T0.Y, T0.W, literal.x, PV.W, -; CM-NEXT: ADD T0.Z, T0.Z, -T2.W, -; CM-NEXT: FLT_TO_INT * T0.W, PV.Z, +; CM-NEXT: MULADD_IEEE T0.Z, T0.W, literal.x, PV.W, +; CM-NEXT: ADD * T0.W, T2.W, -PV.Z, BS:VEC_120/SCL_212 ; CM-NEXT: 967029397(3.122284e-04), 0(0.000000e+00) -; CM-NEXT: MIN_INT T1.Z, PV.W, literal.x, -; CM-NEXT: ADD * T1.W, PV.Z, PV.Y, +; CM-NEXT: TRUNC T1.Z, T1.Z, +; CM-NEXT: ADD * T0.W, PV.W, PV.Z, +; CM-NEXT: EXP_IEEE T0.X, T0.W, +; CM-NEXT: EXP_IEEE T0.Y (MASKED), T0.W, +; CM-NEXT: EXP_IEEE T0.Z (MASKED), T0.W, +; CM-NEXT: EXP_IEEE * T0.W (MASKED), T0.W, +; CM-NEXT: FLT_TO_INT T0.Z, T1.Z, +; CM-NEXT: MUL_IEEE * T0.W, PV.X, literal.x, +; CM-NEXT: 209715200(1.972152e-31), 0(0.000000e+00) +; CM-NEXT: MUL_IEEE T0.Y, PV.W, literal.x, +; CM-NEXT: MAX_INT T1.Z, PV.Z, literal.y, +; CM-NEXT: MIN_INT * T1.W, PV.Z, literal.z, +; CM-NEXT: 209715200(1.972152e-31), -330(nan) ; CM-NEXT: 381(5.338947e-43), 0(0.000000e+00) -; CM-NEXT: EXP_IEEE T0.X, T1.W, -; CM-NEXT: EXP_IEEE T0.Y (MASKED), T1.W, -; CM-NEXT: EXP_IEEE T0.Z (MASKED), T1.W, -; CM-NEXT: EXP_IEEE * T0.W (MASKED), T1.W, -; CM-NEXT: MUL_IEEE T0.Y, PV.X, literal.x, -; CM-NEXT: ADD_INT T0.Z, T1.Z, literal.y, -; CM-NEXT: MAX_INT * T1.W, T0.W, literal.z, -; CM-NEXT: 2130706432(1.701412e+38), -254(nan) -; CM-NEXT: -330(nan), 0(0.000000e+00) -; CM-NEXT: ADD_INT T1.X, T0.W, literal.x, -; CM-NEXT: ADD_INT T1.Y, PV.W, literal.y, -; CM-NEXT: ADD_INT T1.Z, T0.W, literal.z, -; CM-NEXT: SETGT_UINT * T1.W, T0.W, literal.w, -; CM-NEXT: -127(nan), 204(2.858649e-43) +; CM-NEXT: ADD_INT T1.X, PV.W, literal.x, +; CM-NEXT: ADD_INT T1.Y, PV.Z, literal.y, +; CM-NEXT: ADD_INT T1.Z, T0.Z, literal.z, +; CM-NEXT: SETGT_UINT * T1.W, T0.Z, literal.w, +; CM-NEXT: -254(nan), 204(2.858649e-43) ; CM-NEXT: 102(1.429324e-43), -229(nan) -; CM-NEXT: SETGT_UINT T2.X, T0.W, literal.x, -; CM-NEXT: CNDE_INT T1.Y, PV.W, PV.Y, PV.Z, -; CM-NEXT: SETGT_INT T1.Z, T0.W, literal.y, -; CM-NEXT: MUL_IEEE * T2.W, T0.X, literal.z, -; CM-NEXT: 254(3.559298e-43), -127(nan) -; CM-NEXT: 209715200(1.972152e-31), 0(0.000000e+00) -; CM-NEXT: MUL_IEEE T3.X, PV.W, literal.x, -; CM-NEXT: CNDE_INT T1.Y, PV.Z, PV.Y, T0.W, -; CM-NEXT: CNDE_INT T0.Z, PV.X, T1.X, T0.Z, -; CM-NEXT: SETGT_INT * T0.W, T0.W, literal.y, -; CM-NEXT: 209715200(1.972152e-31), 127(1.779649e-43) +; CM-NEXT: ADD_INT T2.X, T0.Z, literal.x, +; CM-NEXT: SETGT_UINT T2.Y, T0.Z, literal.y, +; CM-NEXT: CNDE_INT T1.Z, PV.W, PV.Y, PV.Z, +; CM-NEXT: SETGT_INT * T2.W, T0.Z, literal.x, +; CM-NEXT: -127(nan), 254(3.559298e-43) +; CM-NEXT: MUL_IEEE T3.X, T0.X, literal.x, +; CM-NEXT: CNDE_INT T1.Y, PV.W, PV.Z, T0.Z, +; CM-NEXT: CNDE_INT T1.Z, PV.Y, PV.X, T1.X, +; CM-NEXT: SETGT_INT * T3.W, T0.Z, literal.y, +; CM-NEXT: 2130706432(1.701412e+38), 127(1.779649e-43) ; CM-NEXT: CNDE_INT T1.Y, PV.W, PV.Y, PV.Z, -; CM-NEXT: CNDE_INT T0.Z, T1.W, PV.X, T2.W, -; CM-NEXT: MUL_IEEE * T1.W, T0.Y, literal.x, +; CM-NEXT: MUL_IEEE T0.Z, PV.X, literal.x, +; CM-NEXT: CNDE_INT * T0.W, T1.W, T0.Y, T0.W, ; CM-NEXT: 2130706432(1.701412e+38), 0(0.000000e+00) -; CM-NEXT: CNDE_INT T1.X, T2.X, T0.Y, PV.W, -; CM-NEXT: CNDE_INT T0.Y, T1.Z, PV.Z, T0.X, +; CM-NEXT: CNDE_INT T0.X, T2.W, PV.W, T0.X, +; CM-NEXT: CNDE_INT T0.Y, T2.Y, T3.X, PV.Z, ; CM-NEXT: LSHL T0.Z, PV.Y, literal.x, -; CM-NEXT: AND_INT * T1.W, KC0[3].Z, literal.y, +; CM-NEXT: AND_INT * T0.W, KC0[3].Z, literal.y, ; CM-NEXT: 23(3.222986e-44), -4096(nan) -; CM-NEXT: MUL_IEEE T0.X, PV.W, literal.x, ; CM-NEXT: ADD T1.Y, KC0[3].Z, -PV.W, -; CM-NEXT: ADD_INT T0.Z, PV.Z, literal.y, -; CM-NEXT: CNDE_INT * T0.W, T0.W, PV.Y, PV.X, -; CM-NEXT: 1069064192(1.442383e+00), 1065353216(1.000000e+00) -; CM-NEXT: MUL_IEEE T0.Y, PV.W, PV.Z, -; CM-NEXT: MUL_IEEE T0.Z, PV.Y, literal.x, -; CM-NEXT: RNDNE * T0.W, PV.X, -; CM-NEXT: 967029397(3.122284e-04), 0(0.000000e+00) +; CM-NEXT: ADD_INT T0.Z, PV.Z, literal.x, +; CM-NEXT: CNDE_INT * T1.W, T3.W, PV.X, PV.Y, +; CM-NEXT: 1065353216(1.000000e+00), 0(0.000000e+00) +; CM-NEXT: MUL_IEEE T0.X, PV.W, PV.Z, +; CM-NEXT: MUL_IEEE T0.Y, PV.Y, literal.x, +; CM-NEXT: MUL_IEEE T0.Z, T0.W, literal.y, +; CM-NEXT: AND_INT * T1.W, KC0[3].W, literal.z, +; CM-NEXT: 967029397(3.122284e-04), 1069064192(1.442383e+00) +; CM-NEXT: -4096(nan), 0(0.000000e+00) ; CM-NEXT: SETGT T1.X, literal.x, KC0[3].Y, -; CM-NEXT: TRUNC T2.Y, PV.W, -; CM-NEXT: AND_INT T1.Z, KC0[3].W, literal.y, -; CM-NEXT: MULADD_IEEE * T2.W, T1.Y, literal.z, PV.Z, -; CM-NEXT: -1026650416(-1.032789e+02), -4096(nan) -; CM-NEXT: 1069064192(1.442383e+00), 0(0.000000e+00) -; CM-NEXT: MULADD_IEEE T2.X, T1.W, literal.x, PV.W, -; CM-NEXT: MUL_IEEE T1.Y, PV.Z, literal.y, -; CM-NEXT: FLT_TO_INT T0.Z, PV.Y, -; CM-NEXT: ADD * T1.W, KC0[3].W, -PV.Z, +; CM-NEXT: ADD T2.Y, KC0[3].W, -PV.W, +; CM-NEXT: RNDNE T1.Z, PV.Z, +; CM-NEXT: MULADD_IEEE * T2.W, T1.Y, literal.y, PV.Y, +; CM-NEXT: -1026650416(-1.032789e+02), 1069064192(1.442383e+00) +; CM-NEXT: MULADD_IEEE T2.X, T0.W, literal.x, PV.W, +; CM-NEXT: ADD T0.Y, T0.Z, -PV.Z, +; CM-NEXT: MUL_IEEE T0.Z, PV.Y, literal.x, +; CM-NEXT: MUL_IEEE * T0.W, T1.W, literal.y, BS:VEC_120/SCL_212 ; CM-NEXT: 967029397(3.122284e-04), 1069064192(1.442383e+00) -; CM-NEXT: ADD T0.X, T0.X, -T0.W, -; CM-NEXT: MUL_IEEE T2.Y, PV.W, literal.x, -; CM-NEXT: MAX_INT T2.Z, PV.Z, literal.y, -; CM-NEXT: RNDNE * T0.W, PV.Y, -; CM-NEXT: 967029397(3.122284e-04), -330(nan) -; CM-NEXT: TRUNC T3.X, PV.W, -; CM-NEXT: ADD_INT T3.Y, PV.Z, literal.x, -; CM-NEXT: MULADD_IEEE T2.Z, T1.W, literal.y, PV.Y, -; CM-NEXT: ADD * T1.W, PV.X, T2.X, -; CM-NEXT: 204(2.858649e-43), 1069064192(1.442383e+00) -; CM-NEXT: EXP_IEEE T0.X, T1.W, -; CM-NEXT: EXP_IEEE T0.Y (MASKED), T1.W, -; CM-NEXT: EXP_IEEE T0.Z (MASKED), T1.W, -; CM-NEXT: EXP_IEEE * T0.W (MASKED), T1.W, -; CM-NEXT: ADD_INT T2.X, T0.Z, literal.x, -; CM-NEXT: MULADD_IEEE T2.Y, T1.Z, literal.y, T2.Z, BS:VEC_102/SCL_221 -; CM-NEXT: ADD T1.Z, T1.Y, -T0.W, -; CM-NEXT: MUL_IEEE * T0.W, PV.X, literal.z, -; CM-NEXT: 102(1.429324e-43), 967029397(3.122284e-04) -; CM-NEXT: 2130706432(1.701412e+38), 0(0.000000e+00) -; CM-NEXT: SETGT_UINT T4.X, T0.Z, literal.x, -; CM-NEXT: MUL_IEEE T1.Y, PV.W, literal.y, -; CM-NEXT: SETGT_UINT T2.Z, T0.Z, literal.z, -; CM-NEXT: ADD * T1.W, PV.Z, PV.Y, -; CM-NEXT: -229(nan), 2130706432(1.701412e+38) -; CM-NEXT: 254(3.559298e-43), 0(0.000000e+00) +; CM-NEXT: TRUNC T3.X, T1.Z, +; CM-NEXT: RNDNE T1.Y, PV.W, +; CM-NEXT: MULADD_IEEE T0.Z, T2.Y, literal.x, PV.Z, +; CM-NEXT: ADD * T2.W, PV.Y, PV.X, +; CM-NEXT: 1069064192(1.442383e+00), 0(0.000000e+00) +; CM-NEXT: EXP_IEEE T0.X (MASKED), T2.W, +; CM-NEXT: EXP_IEEE T0.Y, T2.W, +; CM-NEXT: EXP_IEEE T0.Z (MASKED), T2.W, +; CM-NEXT: EXP_IEEE * T0.W (MASKED), T2.W, +; CM-NEXT: MULADD_IEEE T2.X, T1.W, literal.x, T0.Z, +; CM-NEXT: ADD T2.Y, T0.W, -T1.Y, BS:VEC_120/SCL_212 +; CM-NEXT: FLT_TO_INT T0.Z, T3.X, +; CM-NEXT: MUL_IEEE * T0.W, PV.Y, literal.y, +; CM-NEXT: 967029397(3.122284e-04), 209715200(1.972152e-31) +; CM-NEXT: MUL_IEEE T3.X, PV.W, literal.x, +; CM-NEXT: SETGT_UINT T3.Y, PV.Z, literal.y, +; CM-NEXT: TRUNC T1.Z, T1.Y, +; CM-NEXT: ADD * T1.W, PV.Y, PV.X, +; CM-NEXT: 209715200(1.972152e-31), -229(nan) ; CM-NEXT: EXP_IEEE T1.X (MASKED), T1.W, -; CM-NEXT: EXP_IEEE T1.Y (MASKED), T1.W, -; CM-NEXT: EXP_IEEE T1.Z, T1.W, +; CM-NEXT: EXP_IEEE T1.Y, T1.W, +; CM-NEXT: EXP_IEEE T1.Z (MASKED), T1.W, ; CM-NEXT: EXP_IEEE * T1.W (MASKED), T1.W, -; CM-NEXT: ALU clause starting at 109: -; CM-NEXT: CNDE_INT T5.X, T2.Z, T0.W, T1.Y, -; CM-NEXT: CNDE_INT T1.Y, T4.X, T3.Y, T2.X, -; CM-NEXT: FLT_TO_INT T3.Z, T3.X, BS:VEC_120/SCL_212 -; CM-NEXT: MUL_IEEE * T0.W, T1.Z, literal.x, BS:VEC_120/SCL_212 -; CM-NEXT: 2130706432(1.701412e+38), 0(0.000000e+00) -; CM-NEXT: SETGT_INT T2.X, T0.Z, literal.x, -; CM-NEXT: MUL_IEEE T2.Y, T0.X, literal.y, -; CM-NEXT: MUL_IEEE T4.Z, PV.W, literal.z, -; CM-NEXT: SETGT_UINT * T1.W, PV.Z, literal.w, -; CM-NEXT: -127(nan), 209715200(1.972152e-31) -; CM-NEXT: 2130706432(1.701412e+38), 254(3.559298e-43) -; CM-NEXT: CNDE_INT T3.X, PV.W, T0.W, PV.Z, -; CM-NEXT: MUL_IEEE T3.Y, PV.Y, literal.x, -; CM-NEXT: CNDE_INT T4.Z, PV.X, T1.Y, T0.Z, -; CM-NEXT: MAX_INT * T0.W, T3.Z, literal.y, -; CM-NEXT: 209715200(1.972152e-31), -330(nan) -; CM-NEXT: ADD_INT T6.X, PV.W, literal.x, -; CM-NEXT: ADD_INT T1.Y, T3.Z, literal.y, -; CM-NEXT: SETGT_UINT T5.Z, T3.Z, literal.z, -; CM-NEXT: MUL_IEEE * T0.W, T1.Z, literal.w, BS:VEC_120/SCL_212 +; CM-NEXT: FLT_TO_INT T2.X, T1.Z, +; CM-NEXT: MUL_IEEE T2.Y, PV.Y, literal.x, +; CM-NEXT: CNDE_INT T1.Z, T3.Y, T3.X, T0.W, +; CM-NEXT: SETGT_INT * T0.W, T0.Z, literal.y, BS:VEC_120/SCL_212 +; CM-NEXT: 209715200(1.972152e-31), -127(nan) +; CM-NEXT: CNDE_INT T3.X, PV.W, PV.Z, T0.Y, +; CM-NEXT: MUL_IEEE * T4.Y, PV.Y, literal.x, +; CM-NEXT: 209715200(1.972152e-31), 0(0.000000e+00) +; CM-NEXT: ALU clause starting at 108: +; CM-NEXT: SETGT_UINT T1.Z, T2.X, literal.x, +; CM-NEXT: MAX_INT * T1.W, T0.Z, literal.y, +; CM-NEXT: -229(nan), -330(nan) +; CM-NEXT: ADD_INT T4.X, PV.W, literal.x, +; CM-NEXT: ADD_INT T5.Y, T0.Z, literal.y, +; CM-NEXT: CNDE_INT T2.Z, PV.Z, T4.Y, T2.Y, +; CM-NEXT: SETGT_INT * T1.W, T2.X, literal.z, ; CM-NEXT: 204(2.858649e-43), 102(1.429324e-43) -; CM-NEXT: -229(nan), 209715200(1.972152e-31) -; CM-NEXT: MUL_IEEE T7.X, PV.W, literal.x, -; CM-NEXT: MIN_INT T4.Y, T3.Z, literal.y, -; CM-NEXT: CNDE_INT T6.Z, PV.Z, PV.X, PV.Y, -; CM-NEXT: SETGT_INT * T2.W, T3.Z, literal.z, -; CM-NEXT: 209715200(1.972152e-31), 381(5.338947e-43) ; CM-NEXT: -127(nan), 0(0.000000e+00) -; CM-NEXT: CNDE_INT T6.X, PV.W, PV.Z, T3.Z, -; CM-NEXT: MIN_INT T1.Y, T0.Z, literal.x, -; CM-NEXT: ADD_INT T6.Z, PV.Y, literal.y, -; CM-NEXT: ADD_INT * T3.W, T3.Z, literal.z, BS:VEC_120/SCL_212 -; CM-NEXT: 381(5.338947e-43), -254(nan) -; CM-NEXT: -127(nan), 0(0.000000e+00) -; CM-NEXT: CNDE_INT T8.X, T1.W, PV.W, PV.Z, -; CM-NEXT: SETGT_INT T4.Y, T3.Z, literal.x, -; CM-NEXT: ADD_INT T3.Z, PV.Y, literal.y, -; CM-NEXT: ADD_INT * T1.W, T0.Z, literal.z, BS:VEC_120/SCL_212 +; CM-NEXT: CNDE_INT T5.X, PV.W, PV.Z, T1.Y, +; CM-NEXT: MUL_IEEE T0.Y, T0.Y, literal.x, +; CM-NEXT: MAX_INT T2.Z, T2.X, literal.y, +; CM-NEXT: CNDE_INT * T2.W, T3.Y, PV.X, PV.Y, BS:VEC_120/SCL_212 +; CM-NEXT: 2130706432(1.701412e+38), -330(nan) +; CM-NEXT: CNDE_INT T4.X, T0.W, PV.W, T0.Z, +; CM-NEXT: ADD_INT T2.Y, PV.Z, literal.x, +; CM-NEXT: ADD_INT T2.Z, T2.X, literal.y, +; CM-NEXT: MIN_INT * T0.W, T2.X, literal.z, +; CM-NEXT: 204(2.858649e-43), 102(1.429324e-43) +; CM-NEXT: 381(5.338947e-43), 0(0.000000e+00) +; CM-NEXT: ADD_INT T6.X, PV.W, literal.x, +; CM-NEXT: ADD_INT T3.Y, T2.X, literal.y, +; CM-NEXT: SETGT_UINT T3.Z, T2.X, literal.z, +; CM-NEXT: CNDE_INT * T0.W, T1.Z, PV.Y, PV.Z, +; CM-NEXT: -254(nan), -127(nan) +; CM-NEXT: 254(3.559298e-43), 0(0.000000e+00) +; CM-NEXT: MUL_IEEE T7.X, T1.Y, literal.x, +; CM-NEXT: CNDE_INT T1.Y, T1.W, PV.W, T2.X, +; CM-NEXT: CNDE_INT T1.Z, PV.Z, PV.Y, PV.X, +; CM-NEXT: MIN_INT * T0.W, T0.Z, literal.y, +; CM-NEXT: 2130706432(1.701412e+38), 381(5.338947e-43) +; CM-NEXT: SETGT_INT T2.X, T2.X, literal.x, +; CM-NEXT: ADD_INT T2.Y, PV.W, literal.y, +; CM-NEXT: ADD_INT T2.Z, T0.Z, literal.z, +; CM-NEXT: SETGT_UINT * T0.W, T0.Z, literal.w, ; CM-NEXT: 127(1.779649e-43), -254(nan) -; CM-NEXT: -127(nan), 0(0.000000e+00) -; CM-NEXT: CNDE_INT T9.X, T2.Z, PV.W, PV.Z, -; CM-NEXT: SETGT_INT T1.Y, T0.Z, literal.x, BS:VEC_120/SCL_212 -; CM-NEXT: CNDE_INT T0.Z, PV.Y, T6.X, PV.X, -; CM-NEXT: CNDE_INT * T0.W, T5.Z, T7.X, T0.W, BS:VEC_201 -; CM-NEXT: 127(1.779649e-43), 0(0.000000e+00) -; CM-NEXT: CNDE_INT T6.X, T2.W, PV.W, T1.Z, -; CM-NEXT: LSHL T5.Y, PV.Z, literal.x, -; CM-NEXT: CNDE_INT T0.Z, PV.Y, T4.Z, PV.X, -; CM-NEXT: CNDE_INT * T0.W, T4.X, T3.Y, T2.Y, -; CM-NEXT: 23(3.222986e-44), 0(0.000000e+00) -; CM-NEXT: CNDE_INT T0.X, T2.X, PV.W, T0.X, -; CM-NEXT: LSHL T2.Y, PV.Z, literal.x, +; CM-NEXT: -127(nan), 254(3.559298e-43) +; CM-NEXT: CNDE_INT T6.X, PV.W, PV.Z, PV.Y, +; CM-NEXT: SETGT_INT T2.Y, T0.Z, literal.x, +; CM-NEXT: CNDE_INT T0.Z, PV.X, T1.Y, T1.Z, +; CM-NEXT: MUL_IEEE * T1.W, T7.X, literal.y, +; CM-NEXT: 127(1.779649e-43), 2130706432(1.701412e+38) +; CM-NEXT: CNDE_INT T7.X, T3.Z, T7.X, PV.W, +; CM-NEXT: LSHL T1.Y, PV.Z, literal.x, +; CM-NEXT: CNDE_INT T0.Z, PV.Y, T4.X, PV.X, BS:VEC_021/SCL_122 +; CM-NEXT: MUL_IEEE * T1.W, T0.Y, literal.y, +; CM-NEXT: 23(3.222986e-44), 2130706432(1.701412e+38) +; CM-NEXT: CNDE_INT T4.X, T0.W, T0.Y, PV.W, +; CM-NEXT: LSHL T0.Y, PV.Z, literal.x, ; CM-NEXT: ADD_INT T0.Z, PV.Y, literal.y, -; CM-NEXT: CNDE_INT * T0.W, T4.Y, PV.X, T3.X, BS:VEC_021/SCL_122 +; CM-NEXT: CNDE_INT * T0.W, T2.X, T5.X, PV.X, ; CM-NEXT: 23(3.222986e-44), 1065353216(1.000000e+00) ; CM-NEXT: MUL_IEEE T2.X, PV.W, PV.Z, -; CM-NEXT: SETGT T3.Y, literal.x, KC0[3].W, +; CM-NEXT: SETGT T1.Y, literal.x, KC0[3].W, ; CM-NEXT: ADD_INT T0.Z, PV.Y, literal.y, -; CM-NEXT: CNDE_INT * T0.W, T1.Y, PV.X, T5.X, +; CM-NEXT: CNDE_INT * T0.W, T2.Y, T3.X, PV.X, ; CM-NEXT: -1026650416(-1.032789e+02), 1065353216(1.000000e+00) -; CM-NEXT: MUL_IEEE T0.X, PV.W, PV.Z, -; CM-NEXT: SETGT T1.Y, literal.x, KC0[3].Z, +; CM-NEXT: MUL_IEEE T3.X, PV.W, PV.Z, +; CM-NEXT: SETGT T0.Y, literal.x, KC0[3].Z, ; CM-NEXT: CNDE T0.Z, PV.Y, PV.X, 0.0, ; CM-NEXT: SETGT * T0.W, KC0[3].W, literal.y, ; CM-NEXT: -1026650416(-1.032789e+02), 1118925336(8.872284e+01) ; CM-NEXT: CNDE T2.X, PV.W, PV.Z, literal.x, -; CM-NEXT: CNDE T1.Y, PV.Y, PV.X, 0.0, +; CM-NEXT: CNDE T0.Y, PV.Y, PV.X, 0.0, ; CM-NEXT: SETGT T0.Z, KC0[3].Z, literal.y, ; CM-NEXT: ADD_INT * T0.W, KC0[2].Y, literal.z, ; CM-NEXT: 2139095040(INF), 1118925336(8.872284e+01) ; CM-NEXT: 8(1.121039e-44), 0(0.000000e+00) -; CM-NEXT: LSHR T0.X, PV.W, literal.x, -; CM-NEXT: CNDE T1.Y, PV.Z, PV.Y, literal.y, -; CM-NEXT: CNDE T0.Z, T1.X, T0.Y, 0.0, +; CM-NEXT: LSHR T3.X, PV.W, literal.x, +; CM-NEXT: CNDE T0.Y, PV.Z, PV.Y, literal.y, +; CM-NEXT: CNDE T0.Z, T1.X, T0.X, 0.0, ; CM-NEXT: SETGT * T0.W, KC0[3].Y, literal.z, ; CM-NEXT: 2(2.802597e-45), 2139095040(INF) ; CM-NEXT: 1118925336(8.872284e+01), 0(0.000000e+00) -; CM-NEXT: CNDE * T1.X, PV.W, PV.Z, literal.x, +; CM-NEXT: CNDE * T0.X, PV.W, PV.Z, literal.x, ; CM-NEXT: 2139095040(INF), 0(0.000000e+00) -; CM-NEXT: LSHR * T3.X, KC0[2].Y, literal.x, +; CM-NEXT: LSHR * T1.X, KC0[2].Y, literal.x, ; CM-NEXT: 2(2.802597e-45), 0(0.000000e+00) %result = call <3 x float> @llvm.exp.v3f32(<3 x float> %in) store <3 x float> %result, ptr addrspace(1) %out @@ -2050,227 +2041,224 @@ define amdgpu_kernel void @s_exp_v4f32(ptr addrspace(1) %out, <4 x float> %in) { ; R600-LABEL: s_exp_v4f32: ; R600: ; %bb.0: ; R600-NEXT: ALU 98, @6, KC0[CB0:0-32], KC1[] -; R600-NEXT: ALU 98, @105, KC0[CB0:0-32], KC1[] -; R600-NEXT: ALU 24, @204, KC0[CB0:0-32], KC1[] +; R600-NEXT: ALU 95, @105, KC0[CB0:0-32], KC1[] +; R600-NEXT: ALU 24, @201, KC0[CB0:0-32], KC1[] ; R600-NEXT: MEM_RAT_CACHELESS STORE_RAW T1.XYZW, T0.X, 1 ; R600-NEXT: CF_END ; R600-NEXT: PAD ; R600-NEXT: ALU clause starting at 6: ; R600-NEXT: AND_INT * T0.W, KC0[3].Z, literal.x, ; R600-NEXT: -4096(nan), 0(0.000000e+00) -; R600-NEXT: ADD T1.W, KC0[3].Z, -PV.W, -; R600-NEXT: MUL_IEEE * T2.W, PV.W, literal.x, +; R600-NEXT: ADD * T1.W, KC0[3].Z, -PV.W, +; R600-NEXT: MUL_IEEE T2.W, PV.W, literal.x, +; R600-NEXT: MUL_IEEE * T3.W, T0.W, literal.y, +; R600-NEXT: 967029397(3.122284e-04), 1069064192(1.442383e+00) +; R600-NEXT: RNDNE T4.W, PS, +; R600-NEXT: MULADD_IEEE * T1.W, T1.W, literal.x, PV.W, BS:VEC_021/SCL_122 ; R600-NEXT: 1069064192(1.442383e+00), 0(0.000000e+00) -; R600-NEXT: RNDNE T3.W, PS, -; R600-NEXT: MUL_IEEE * T4.W, PV.W, literal.x, +; R600-NEXT: MULADD_IEEE T0.W, T0.W, literal.x, PS, +; R600-NEXT: ADD * T1.W, T3.W, -PV.W, ; R600-NEXT: 967029397(3.122284e-04), 0(0.000000e+00) -; R600-NEXT: MULADD_IEEE T1.W, T1.W, literal.x, PS, -; R600-NEXT: TRUNC * T4.W, PV.W, -; R600-NEXT: 1069064192(1.442383e+00), 0(0.000000e+00) -; R600-NEXT: FLT_TO_INT T0.Z, PS, -; R600-NEXT: MULADD_IEEE T0.W, T0.W, literal.x, PV.W, -; R600-NEXT: ADD * T1.W, T2.W, -T3.W, -; R600-NEXT: 967029397(3.122284e-04), 0(0.000000e+00) -; R600-NEXT: ADD T1.Z, PS, PV.W, -; R600-NEXT: MAX_INT T0.W, PV.Z, literal.x, -; R600-NEXT: MIN_INT * T1.W, PV.Z, literal.y, -; R600-NEXT: -330(nan), 381(5.338947e-43) -; R600-NEXT: ADD_INT T0.X, PS, literal.x, -; R600-NEXT: ADD_INT T0.Y, PV.W, literal.y, -; R600-NEXT: ADD_INT T2.Z, T0.Z, literal.z, -; R600-NEXT: SETGT_UINT T0.W, T0.Z, literal.w, -; R600-NEXT: EXP_IEEE * T1.X, PV.Z, -; R600-NEXT: -254(nan), 204(2.858649e-43) -; R600-NEXT: 102(1.429324e-43), -229(nan) -; R600-NEXT: ADD_INT T2.X, T0.Z, literal.x, -; R600-NEXT: SETGT_UINT T1.Y, T0.Z, literal.y, -; R600-NEXT: CNDE_INT T1.Z, PV.W, PV.Y, PV.Z, -; R600-NEXT: SETGT_INT T1.W, T0.Z, literal.x, -; R600-NEXT: MUL_IEEE * T2.W, PS, literal.z, -; R600-NEXT: -127(nan), 254(3.559298e-43) -; R600-NEXT: 209715200(1.972152e-31), 0(0.000000e+00) -; R600-NEXT: MUL_IEEE T3.X, T1.X, literal.x, -; R600-NEXT: MUL_IEEE T0.Y, PS, literal.y, -; R600-NEXT: CNDE_INT T1.Z, PV.W, PV.Z, T0.Z, -; R600-NEXT: CNDE_INT T3.W, PV.Y, PV.X, T0.X, -; R600-NEXT: SETGT_INT * T4.W, T0.Z, literal.z, -; R600-NEXT: 2130706432(1.701412e+38), 209715200(1.972152e-31) -; R600-NEXT: 127(1.779649e-43), 0(0.000000e+00) -; R600-NEXT: AND_INT T2.Y, KC0[4].X, literal.x, -; R600-NEXT: CNDE_INT T0.Z, PS, PV.Z, PV.W, -; R600-NEXT: CNDE_INT T0.W, T0.W, PV.Y, T2.W, -; R600-NEXT: MUL_IEEE * T2.W, PV.X, literal.y, -; R600-NEXT: -4096(nan), 2130706432(1.701412e+38) -; R600-NEXT: CNDE_INT T0.X, T1.Y, T3.X, PS, -; R600-NEXT: CNDE_INT T0.Y, T1.W, PV.W, T1.X, -; R600-NEXT: LSHL T0.Z, PV.Z, literal.x, -; R600-NEXT: ADD T0.W, KC0[4].X, -PV.Y, -; R600-NEXT: MUL_IEEE * T1.W, PV.Y, literal.y, -; R600-NEXT: 23(3.222986e-44), 1069064192(1.442383e+00) -; R600-NEXT: RNDNE T1.Y, PS, -; R600-NEXT: MUL_IEEE T1.Z, PV.W, literal.x, -; R600-NEXT: ADD_INT T2.W, PV.Z, literal.y, -; R600-NEXT: CNDE_INT * T3.W, T4.W, PV.Y, PV.X, -; R600-NEXT: 967029397(3.122284e-04), 1065353216(1.000000e+00) -; R600-NEXT: MUL_IEEE T0.Y, PS, PV.W, -; R600-NEXT: AND_INT T0.Z, KC0[3].W, literal.x, -; R600-NEXT: MULADD_IEEE T0.W, T0.W, literal.y, PV.Z, -; R600-NEXT: TRUNC * T2.W, PV.Y, -; R600-NEXT: -4096(nan), 1069064192(1.442383e+00) -; R600-NEXT: SETGT T0.X, literal.x, KC0[3].Z, -; R600-NEXT: FLT_TO_INT T3.Y, PS, -; R600-NEXT: MULADD_IEEE T1.Z, T2.Y, literal.y, PV.W, -; R600-NEXT: ADD T0.W, T1.W, -T1.Y, -; R600-NEXT: MUL_IEEE * T1.W, PV.Z, literal.z, -; R600-NEXT: -1026650416(-1.032789e+02), 967029397(3.122284e-04) -; R600-NEXT: 1069064192(1.442383e+00), 0(0.000000e+00) -; R600-NEXT: RNDNE T1.X, PS, -; R600-NEXT: AND_INT T1.Y, KC0[3].Y, literal.x, -; R600-NEXT: ADD T1.Z, PV.W, PV.Z, -; R600-NEXT: MAX_INT T0.W, PV.Y, literal.y, -; R600-NEXT: MIN_INT * T2.W, PV.Y, literal.z, -; R600-NEXT: -4096(nan), -330(nan) +; R600-NEXT: ADD T0.W, PS, PV.W, +; R600-NEXT: TRUNC * T1.W, T4.W, +; R600-NEXT: FLT_TO_INT T1.W, PS, +; R600-NEXT: EXP_IEEE * T0.X, PV.W, +; R600-NEXT: MUL_IEEE T0.Z, PS, literal.x, +; R600-NEXT: MAX_INT T0.W, PV.W, literal.y, +; R600-NEXT: MIN_INT * T2.W, PV.W, literal.z, +; R600-NEXT: 209715200(1.972152e-31), -330(nan) ; R600-NEXT: 381(5.338947e-43), 0(0.000000e+00) -; R600-NEXT: ADD_INT T2.X, PS, literal.x, -; R600-NEXT: ADD_INT T2.Y, PV.W, literal.y, -; R600-NEXT: ADD_INT T2.Z, T3.Y, literal.z, -; R600-NEXT: SETGT_UINT T0.W, T3.Y, literal.w, -; R600-NEXT: EXP_IEEE * T1.Z, PV.Z, -; R600-NEXT: -254(nan), 204(2.858649e-43) -; R600-NEXT: 102(1.429324e-43), -229(nan) -; R600-NEXT: ADD_INT T3.X, T3.Y, literal.x, -; R600-NEXT: SETGT_UINT T4.Y, T3.Y, literal.y, -; R600-NEXT: CNDE_INT T2.Z, PV.W, PV.Y, PV.Z, -; R600-NEXT: SETGT_INT T2.W, T3.Y, literal.x, -; R600-NEXT: MUL_IEEE * T3.W, PS, literal.z, +; R600-NEXT: ADD_INT T1.X, PS, literal.x, +; R600-NEXT: AND_INT T0.Y, KC0[4].X, literal.y, +; R600-NEXT: ADD_INT T1.Z, PV.W, literal.z, +; R600-NEXT: ADD_INT * T0.W, T1.W, literal.w, +; R600-NEXT: -254(nan), -4096(nan) +; R600-NEXT: 204(2.858649e-43), 102(1.429324e-43) +; R600-NEXT: SETGT_UINT * T2.W, T1.W, literal.x, +; R600-NEXT: -229(nan), 0(0.000000e+00) +; R600-NEXT: ADD_INT T2.X, T1.W, literal.x, +; R600-NEXT: SETGT_UINT T1.Y, T1.W, literal.y, +; R600-NEXT: CNDE_INT T1.Z, PV.W, T1.Z, T0.W, +; R600-NEXT: SETGT_INT T0.W, T1.W, literal.x, +; R600-NEXT: ADD * T3.W, KC0[4].X, -T0.Y, ; R600-NEXT: -127(nan), 254(3.559298e-43) -; R600-NEXT: 209715200(1.972152e-31), 0(0.000000e+00) -; R600-NEXT: MUL_IEEE T4.X, T1.Z, literal.x, -; R600-NEXT: MUL_IEEE T2.Y, PS, literal.y, -; R600-NEXT: CNDE_INT T2.Z, PV.W, PV.Z, T3.Y, -; R600-NEXT: CNDE_INT T4.W, PV.Y, PV.X, T2.X, -; R600-NEXT: SETGT_INT * T5.W, T3.Y, literal.z, -; R600-NEXT: 2130706432(1.701412e+38), 209715200(1.972152e-31) +; R600-NEXT: MUL_IEEE T3.X, PS, literal.x, +; R600-NEXT: MUL_IEEE T2.Y, T0.Y, literal.y, +; R600-NEXT: CNDE_INT T1.Z, PV.W, PV.Z, T1.W, +; R600-NEXT: CNDE_INT T4.W, PV.Y, PV.X, T1.X, +; R600-NEXT: SETGT_INT * T1.W, T1.W, literal.z, +; R600-NEXT: 967029397(3.122284e-04), 1069064192(1.442383e+00) ; R600-NEXT: 127(1.779649e-43), 0(0.000000e+00) -; R600-NEXT: ADD T2.X, KC0[3].W, -T0.Z, -; R600-NEXT: CNDE_INT T3.Y, PS, PV.Z, PV.W, -; R600-NEXT: CNDE_INT * T2.Z, T0.W, PV.Y, T3.W, -; R600-NEXT: ALU clause starting at 105: -; R600-NEXT: MUL_IEEE T0.W, T4.X, literal.x, -; R600-NEXT: ADD * T3.W, KC0[3].Y, -T1.Y, +; R600-NEXT: CNDE_INT T1.X, PS, PV.Z, PV.W, +; R600-NEXT: RNDNE T3.Y, PV.Y, +; R600-NEXT: MULADD_IEEE T1.Z, T3.W, literal.x, PV.X, +; R600-NEXT: MUL_IEEE T3.W, T0.Z, literal.y, +; R600-NEXT: MUL_IEEE * T4.W, T0.X, literal.z, +; R600-NEXT: 1069064192(1.442383e+00), 209715200(1.972152e-31) ; R600-NEXT: 2130706432(1.701412e+38), 0(0.000000e+00) +; R600-NEXT: MUL_IEEE T2.X, PS, literal.x, +; R600-NEXT: CNDE_INT T4.Y, T2.W, PV.W, T0.Z, +; R600-NEXT: MULADD_IEEE T0.Z, T0.Y, literal.y, PV.Z, +; R600-NEXT: ADD T2.W, T2.Y, -PV.Y, BS:VEC_120/SCL_212 +; R600-NEXT: AND_INT * T3.W, KC0[3].Y, literal.z, +; R600-NEXT: 2130706432(1.701412e+38), 967029397(3.122284e-04) +; R600-NEXT: -4096(nan), 0(0.000000e+00) ; R600-NEXT: MUL_IEEE T3.X, PS, literal.x, -; R600-NEXT: MUL_IEEE T2.Y, T1.Y, literal.y, -; R600-NEXT: CNDE_INT T3.Z, T4.Y, T4.X, PV.W, BS:VEC_120/SCL_212 -; R600-NEXT: CNDE_INT T0.W, T2.W, T2.Z, T1.Z, -; R600-NEXT: LSHL * T2.W, T3.Y, literal.z, -; R600-NEXT: 967029397(3.122284e-04), 1069064192(1.442383e+00) -; R600-NEXT: 23(3.222986e-44), 0(0.000000e+00) -; R600-NEXT: ADD_INT T4.X, PS, literal.x, -; R600-NEXT: CNDE_INT T3.Y, T5.W, PV.W, PV.Z, -; R600-NEXT: RNDNE T1.Z, PV.Y, -; R600-NEXT: MULADD_IEEE T0.W, T3.W, literal.y, PV.X, BS:VEC_120/SCL_212 -; R600-NEXT: MUL_IEEE * T2.W, T2.X, literal.z, +; R600-NEXT: ADD T0.Y, PV.W, PV.Z, +; R600-NEXT: CNDE_INT T0.Z, T0.W, PV.Y, T0.X, BS:VEC_021/SCL_122 +; R600-NEXT: CNDE_INT T0.W, T1.Y, T4.W, PV.X, +; R600-NEXT: LSHL * T2.W, T1.X, literal.y, +; R600-NEXT: 1069064192(1.442383e+00), 23(3.222986e-44) +; R600-NEXT: AND_INT T0.X, KC0[3].W, literal.x, +; R600-NEXT: TRUNC T1.Y, T3.Y, +; R600-NEXT: ADD_INT T1.Z, PS, literal.y, +; R600-NEXT: CNDE_INT T0.W, T1.W, PV.Z, PV.W, +; R600-NEXT: EXP_IEEE * T0.Y, PV.Y, +; R600-NEXT: -4096(nan), 1065353216(1.000000e+00) +; R600-NEXT: MUL_IEEE T1.X, PV.W, PV.Z, +; R600-NEXT: FLT_TO_INT T1.Y, PV.Y, +; R600-NEXT: MUL_IEEE T0.Z, PS, literal.x, +; R600-NEXT: ADD T0.W, KC0[3].W, -PV.X, +; R600-NEXT: RNDNE * T1.W, T3.X, +; R600-NEXT: 209715200(1.972152e-31), 0(0.000000e+00) +; R600-NEXT: SETGT T2.X, literal.x, KC0[3].Z, +; R600-NEXT: TRUNC T2.Y, PS, +; R600-NEXT: MUL_IEEE T1.Z, PV.W, literal.y, +; R600-NEXT: MUL_IEEE T2.W, PV.Z, literal.z, +; R600-NEXT: MAX_INT * T4.W, PV.Y, literal.w, +; R600-NEXT: -1026650416(-1.032789e+02), 967029397(3.122284e-04) +; R600-NEXT: 209715200(1.972152e-31), -330(nan) +; R600-NEXT: ADD T4.X, KC0[3].Y, -T3.W, +; R600-NEXT: ADD_INT T3.Y, PS, literal.x, +; R600-NEXT: ADD_INT T2.Z, T1.Y, literal.y, +; R600-NEXT: SETGT_UINT T4.W, T1.Y, literal.z, +; R600-NEXT: MIN_INT * T5.W, T1.Y, literal.w, +; R600-NEXT: 204(2.858649e-43), 102(1.429324e-43) +; R600-NEXT: -229(nan), 381(5.338947e-43) +; R600-NEXT: ADD_INT T5.X, PS, literal.x, +; R600-NEXT: ADD_INT T4.Y, T1.Y, literal.y, +; R600-NEXT: SETGT_UINT T3.Z, T1.Y, literal.z, +; R600-NEXT: CNDE_INT T5.W, PV.W, PV.Y, PV.Z, +; R600-NEXT: SETGT_INT * T6.W, T1.Y, literal.y, +; R600-NEXT: -254(nan), -127(nan) +; R600-NEXT: 254(3.559298e-43), 0(0.000000e+00) +; R600-NEXT: MUL_IEEE T6.X, T0.Y, literal.x, +; R600-NEXT: CNDE_INT T3.Y, PS, PV.W, T1.Y, +; R600-NEXT: CNDE_INT * T2.Z, PV.Z, PV.Y, PV.X, +; R600-NEXT: 2130706432(1.701412e+38), 0(0.000000e+00) +; R600-NEXT: ALU clause starting at 105: +; R600-NEXT: SETGT_INT T5.W, T1.Y, literal.x, +; R600-NEXT: MUL_IEEE * T7.W, T4.X, literal.y, +; R600-NEXT: 127(1.779649e-43), 967029397(3.122284e-04) +; R600-NEXT: MUL_IEEE T5.X, T0.X, literal.x, +; R600-NEXT: MULADD_IEEE T1.Y, T4.X, literal.x, PS, BS:VEC_120/SCL_212 +; R600-NEXT: CNDE_INT T2.Z, PV.W, T3.Y, T2.Z, +; R600-NEXT: MUL_IEEE T7.W, T6.X, literal.y, BS:VEC_201 +; R600-NEXT: CNDE_INT * T2.W, T4.W, T2.W, T0.Z, +; R600-NEXT: 1069064192(1.442383e+00), 2130706432(1.701412e+38) +; R600-NEXT: CNDE_INT T4.X, T6.W, PS, T0.Y, +; R600-NEXT: CNDE_INT T0.Y, T3.Z, T6.X, PV.W, +; R600-NEXT: LSHL T0.Z, PV.Z, literal.x, +; R600-NEXT: MULADD_IEEE T2.W, T3.W, literal.y, PV.Y, BS:VEC_201 +; R600-NEXT: ADD * T1.W, T3.X, -T1.W, +; R600-NEXT: 23(3.222986e-44), 967029397(3.122284e-04) +; R600-NEXT: ADD T3.X, PS, PV.W, +; R600-NEXT: ADD_INT T1.Y, PV.Z, literal.x, +; R600-NEXT: CNDE_INT T0.Z, T5.W, PV.X, PV.Y, +; R600-NEXT: RNDNE T1.W, T5.X, +; R600-NEXT: MULADD_IEEE * T0.W, T0.W, literal.y, T1.Z, BS:VEC_021/SCL_122 ; R600-NEXT: 1065353216(1.000000e+00), 1069064192(1.442383e+00) -; R600-NEXT: 967029397(3.122284e-04), 0(0.000000e+00) -; R600-NEXT: MULADD_IEEE T2.X, T2.X, literal.x, PS, -; R600-NEXT: MULADD_IEEE T1.Y, T1.Y, literal.y, PV.W, -; R600-NEXT: ADD T2.Z, T2.Y, -PV.Z, BS:VEC_120/SCL_212 -; R600-NEXT: MUL_IEEE T0.W, PV.Y, PV.X, -; R600-NEXT: SETGT * T2.W, literal.z, KC0[4].X, -; R600-NEXT: 1069064192(1.442383e+00), 967029397(3.122284e-04) -; R600-NEXT: -1026650416(-1.032789e+02), 0(0.000000e+00) -; R600-NEXT: CNDE T3.X, PS, PV.W, 0.0, -; R600-NEXT: ADD T1.Y, PV.Z, PV.Y, -; R600-NEXT: TRUNC T1.Z, T1.Z, -; R600-NEXT: MULADD_IEEE T0.W, T0.Z, literal.x, PV.X, BS:VEC_120/SCL_212 -; R600-NEXT: ADD * T1.W, T1.W, -T1.X, -; R600-NEXT: 967029397(3.122284e-04), 0(0.000000e+00) -; R600-NEXT: SETGT T2.X, KC0[4].X, literal.x, -; R600-NEXT: ADD T2.Y, PS, PV.W, -; R600-NEXT: FLT_TO_INT T0.Z, PV.Z, -; R600-NEXT: TRUNC T0.W, T1.X, -; R600-NEXT: EXP_IEEE * T1.X, PV.Y, -; R600-NEXT: 1118925336(8.872284e+01), 0(0.000000e+00) -; R600-NEXT: MUL_IEEE T4.X, PS, literal.x, -; R600-NEXT: FLT_TO_INT T1.Y, PV.W, -; R600-NEXT: MAX_INT T1.Z, PV.Z, literal.y, -; R600-NEXT: MUL_IEEE T0.W, PS, literal.z, -; R600-NEXT: EXP_IEEE * T1.W, PV.Y, -; R600-NEXT: 2130706432(1.701412e+38), -330(nan) +; R600-NEXT: MULADD_IEEE T0.X, T0.X, literal.x, PS, +; R600-NEXT: ADD T0.Y, T5.X, -PV.W, BS:VEC_120/SCL_212 +; R600-NEXT: MUL_IEEE T0.Z, PV.Z, PV.Y, +; R600-NEXT: SETGT T0.W, literal.y, KC0[4].X, +; R600-NEXT: EXP_IEEE * T1.Y, PV.X, +; R600-NEXT: 967029397(3.122284e-04), -1026650416(-1.032789e+02) +; R600-NEXT: CNDE T3.X, PV.W, PV.Z, 0.0, +; R600-NEXT: ADD T0.Y, PV.Y, PV.X, +; R600-NEXT: FLT_TO_INT T0.Z, T2.Y, +; R600-NEXT: TRUNC T0.W, T1.W, +; R600-NEXT: MUL_IEEE * T1.W, PS, literal.x, ; R600-NEXT: 209715200(1.972152e-31), 0(0.000000e+00) -; R600-NEXT: MUL_IEEE T5.X, PV.W, literal.x, -; R600-NEXT: MUL_IEEE T2.Y, PS, literal.x, -; R600-NEXT: ADD_INT T1.Z, PV.Z, literal.y, -; R600-NEXT: ADD_INT T2.W, T0.Z, literal.z, -; R600-NEXT: MAX_INT * T3.W, PV.Y, literal.w, -; R600-NEXT: 209715200(1.972152e-31), 204(2.858649e-43) -; R600-NEXT: 102(1.429324e-43), -330(nan) -; R600-NEXT: SETGT_UINT T6.X, T0.Z, literal.x, -; R600-NEXT: ADD_INT T3.Y, PS, literal.y, -; R600-NEXT: ADD_INT T2.Z, T1.Y, literal.z, -; R600-NEXT: SETGT_UINT T3.W, T1.Y, literal.x, -; R600-NEXT: MIN_INT * T4.W, T1.Y, literal.w, +; R600-NEXT: SETGT T0.X, KC0[4].X, literal.x, +; R600-NEXT: MUL_IEEE T2.Y, PS, literal.y, +; R600-NEXT: FLT_TO_INT T1.Z, PV.W, +; R600-NEXT: MAX_INT T0.W, PV.Z, literal.z, +; R600-NEXT: EXP_IEEE * T0.Y, PV.Y, +; R600-NEXT: 1118925336(8.872284e+01), 209715200(1.972152e-31) +; R600-NEXT: -330(nan), 0(0.000000e+00) +; R600-NEXT: MUL_IEEE T4.X, T1.Y, literal.x, +; R600-NEXT: MUL_IEEE T3.Y, PS, literal.y, +; R600-NEXT: ADD_INT T2.Z, PV.W, literal.z, +; R600-NEXT: ADD_INT * T0.W, T0.Z, literal.w, +; R600-NEXT: 2130706432(1.701412e+38), 209715200(1.972152e-31) +; R600-NEXT: 204(2.858649e-43), 102(1.429324e-43) +; R600-NEXT: MAX_INT * T2.W, T1.Z, literal.x, +; R600-NEXT: -330(nan), 0(0.000000e+00) +; R600-NEXT: SETGT_UINT T5.X, T0.Z, literal.x, +; R600-NEXT: ADD_INT T4.Y, PV.W, literal.y, +; R600-NEXT: ADD_INT T3.Z, T1.Z, literal.z, BS:VEC_120/SCL_212 +; R600-NEXT: SETGT_UINT T2.W, T1.Z, literal.x, BS:VEC_120/SCL_212 +; R600-NEXT: MIN_INT * T3.W, T1.Z, literal.w, ; R600-NEXT: -229(nan), 204(2.858649e-43) ; R600-NEXT: 102(1.429324e-43), 381(5.338947e-43) -; R600-NEXT: ADD_INT T7.X, PS, literal.x, -; R600-NEXT: ADD_INT T4.Y, T1.Y, literal.y, -; R600-NEXT: SETGT_UINT T3.Z, T1.Y, literal.z, -; R600-NEXT: CNDE_INT T4.W, PV.W, PV.Y, PV.Z, -; R600-NEXT: SETGT_INT * T5.W, T1.Y, literal.y, +; R600-NEXT: ADD_INT T6.X, PS, literal.x, +; R600-NEXT: ADD_INT T5.Y, T1.Z, literal.y, +; R600-NEXT: SETGT_UINT T4.Z, T1.Z, literal.z, +; R600-NEXT: CNDE_INT T3.W, PV.W, PV.Y, PV.Z, +; R600-NEXT: SETGT_INT * T4.W, T1.Z, literal.y, ; R600-NEXT: -254(nan), -127(nan) ; R600-NEXT: 254(3.559298e-43), 0(0.000000e+00) -; R600-NEXT: CNDE_INT T8.X, PS, PV.W, T1.Y, -; R600-NEXT: CNDE_INT T3.Y, PV.Z, PV.Y, PV.X, -; R600-NEXT: SETGT_INT T2.Z, T1.Y, literal.x, -; R600-NEXT: CNDE_INT T2.W, T6.X, T1.Z, T2.W, -; R600-NEXT: SETGT_INT * T4.W, T0.Z, literal.y, +; R600-NEXT: CNDE_INT T7.X, PS, PV.W, T1.Z, BS:VEC_021/SCL_122 +; R600-NEXT: CNDE_INT T4.Y, PV.Z, PV.Y, PV.X, +; R600-NEXT: SETGT_INT T1.Z, T1.Z, literal.x, BS:VEC_120/SCL_212 +; R600-NEXT: CNDE_INT T0.W, T5.X, T2.Z, T0.W, BS:VEC_102/SCL_221 +; R600-NEXT: SETGT_INT * T3.W, T0.Z, literal.y, ; R600-NEXT: 127(1.779649e-43), -127(nan) -; R600-NEXT: CNDE_INT T7.X, PS, PV.W, T0.Z, -; R600-NEXT: CNDE_INT T1.Y, PV.Z, PV.X, PV.Y, -; R600-NEXT: MIN_INT T1.Z, T0.Z, literal.x, -; R600-NEXT: MUL_IEEE T2.W, T1.W, literal.y, -; R600-NEXT: MUL_IEEE * T6.W, T2.Y, literal.z, -; R600-NEXT: 381(5.338947e-43), 2130706432(1.701412e+38) -; R600-NEXT: 209715200(1.972152e-31), 0(0.000000e+00) -; R600-NEXT: CNDE_INT T8.X, T3.W, PS, T2.Y, -; R600-NEXT: MUL_IEEE T2.Y, PV.W, literal.x, -; R600-NEXT: ADD_INT T1.Z, PV.Z, literal.y, -; R600-NEXT: ADD_INT T3.W, T0.Z, literal.z, -; R600-NEXT: SETGT_UINT * T6.W, T0.Z, literal.w, +; R600-NEXT: CNDE_INT T6.X, PS, PV.W, T0.Z, +; R600-NEXT: CNDE_INT T4.Y, PV.Z, PV.X, PV.Y, +; R600-NEXT: MIN_INT T2.Z, T0.Z, literal.x, +; R600-NEXT: MUL_IEEE T0.W, T3.Y, literal.y, +; R600-NEXT: MUL_IEEE * T5.W, T0.Y, literal.z, +; R600-NEXT: 381(5.338947e-43), 209715200(1.972152e-31) +; R600-NEXT: 2130706432(1.701412e+38), 0(0.000000e+00) +; R600-NEXT: MUL_IEEE T7.X, PS, literal.x, +; R600-NEXT: CNDE_INT T3.Y, T2.W, PV.W, T3.Y, +; R600-NEXT: ADD_INT T2.Z, PV.Z, literal.y, +; R600-NEXT: ADD_INT T0.W, T0.Z, literal.z, +; R600-NEXT: SETGT_UINT * T2.W, T0.Z, literal.w, ; R600-NEXT: 2130706432(1.701412e+38), -254(nan) ; R600-NEXT: -127(nan), 254(3.559298e-43) -; R600-NEXT: CNDE_INT T9.X, PS, PV.W, PV.Z, -; R600-NEXT: SETGT_INT T3.Y, T0.Z, literal.x, -; R600-NEXT: CNDE_INT T0.Z, T3.Z, T2.W, PV.Y, BS:VEC_120/SCL_212 -; R600-NEXT: CNDE_INT T1.W, T5.W, PV.X, T1.W, BS:VEC_021/SCL_122 -; R600-NEXT: LSHL * T2.W, T1.Y, literal.y, +; R600-NEXT: CNDE_INT T8.X, PS, PV.W, PV.Z, +; R600-NEXT: SETGT_INT T5.Y, T0.Z, literal.x, +; R600-NEXT: CNDE_INT T0.Z, T4.W, PV.Y, T0.Y, BS:VEC_021/SCL_122 +; R600-NEXT: CNDE_INT T0.W, T4.Z, T5.W, PV.X, BS:VEC_120/SCL_212 +; R600-NEXT: LSHL * T4.W, T4.Y, literal.y, ; R600-NEXT: 127(1.779649e-43), 23(3.222986e-44) -; R600-NEXT: ADD_INT T8.X, PS, literal.x, -; R600-NEXT: CNDE_INT T1.Y, T2.Z, PV.W, PV.Z, -; R600-NEXT: CNDE_INT T0.Z, PV.Y, T7.X, PV.X, -; R600-NEXT: CNDE_INT * T0.W, T6.X, T5.X, T0.W, BS:VEC_021/SCL_122 -; R600-NEXT: 1065353216(1.000000e+00), 0(0.000000e+00) -; R600-NEXT: MUL_IEEE * T1.W, T4.X, literal.x, -; R600-NEXT: 2130706432(1.701412e+38), 0(0.000000e+00) -; R600-NEXT: CNDE_INT T4.X, T6.W, T4.X, PV.W, -; R600-NEXT: CNDE_INT * T2.Y, T4.W, T0.W, T1.X, BS:VEC_120/SCL_212 -; R600-NEXT: ALU clause starting at 204: +; R600-NEXT: ADD_INT T7.X, PS, literal.x, +; R600-NEXT: CNDE_INT T0.Y, T1.Z, PV.Z, PV.W, +; R600-NEXT: CNDE_INT T0.Z, PV.Y, T6.X, PV.X, +; R600-NEXT: MUL_IEEE T0.W, T4.X, literal.y, +; R600-NEXT: CNDE_INT * T1.W, T5.X, T2.Y, T1.W, +; R600-NEXT: 1065353216(1.000000e+00), 2130706432(1.701412e+38) +; R600-NEXT: CNDE_INT T5.X, T3.W, PS, T1.Y, +; R600-NEXT: CNDE_INT * T1.Y, T2.W, T4.X, PV.W, BS:VEC_120/SCL_212 +; R600-NEXT: ALU clause starting at 201: ; R600-NEXT: LSHL T0.Z, T0.Z, literal.x, -; R600-NEXT: MUL_IEEE T0.W, T1.Y, T8.X, +; R600-NEXT: MUL_IEEE T0.W, T0.Y, T7.X, ; R600-NEXT: SETGT * T1.W, literal.y, KC0[3].W, ; R600-NEXT: 23(3.222986e-44), -1026650416(-1.032789e+02) -; R600-NEXT: CNDE T1.X, PS, PV.W, 0.0, -; R600-NEXT: SETGT T1.Y, KC0[3].W, literal.x, +; R600-NEXT: CNDE T4.X, PS, PV.W, 0.0, +; R600-NEXT: SETGT T0.Y, KC0[3].W, literal.x, ; R600-NEXT: ADD_INT T0.Z, PV.Z, literal.y, -; R600-NEXT: CNDE_INT T0.W, T3.Y, T2.Y, T4.X, BS:VEC_120/SCL_212 -; R600-NEXT: CNDE * T1.W, T2.X, T3.X, literal.z, +; R600-NEXT: CNDE_INT T0.W, T5.Y, T5.X, T1.Y, BS:VEC_102/SCL_221 +; R600-NEXT: CNDE * T1.W, T0.X, T3.X, literal.z, ; R600-NEXT: 1118925336(8.872284e+01), 1065353216(1.000000e+00) ; R600-NEXT: 2139095040(INF), 0(0.000000e+00) -; R600-NEXT: MUL_IEEE T2.X, PV.W, PV.Z, +; R600-NEXT: MUL_IEEE T0.X, PV.W, PV.Z, ; R600-NEXT: SETGT T2.Y, literal.x, KC0[3].Y, ; R600-NEXT: CNDE T1.Z, PV.Y, PV.X, literal.y, -; R600-NEXT: CNDE T0.W, T0.X, T0.Y, 0.0, +; R600-NEXT: CNDE T0.W, T2.X, T1.X, 0.0, ; R600-NEXT: SETGT * T2.W, KC0[3].Z, literal.z, ; R600-NEXT: -1026650416(-1.032789e+02), 2139095040(INF) ; R600-NEXT: 1118925336(8.872284e+01), 0(0.000000e+00) @@ -2285,8 +2273,8 @@ define amdgpu_kernel void @s_exp_v4f32(ptr addrspace(1) %out, <4 x float> %in) { ; CM-LABEL: s_exp_v4f32: ; CM: ; %bb.0: ; CM-NEXT: ALU 97, @6, KC0[CB0:0-32], KC1[] -; CM-NEXT: ALU 100, @104, KC0[CB0:0-32], KC1[] -; CM-NEXT: ALU 36, @205, KC0[CB0:0-32], KC1[] +; CM-NEXT: ALU 97, @104, KC0[CB0:0-32], KC1[] +; CM-NEXT: ALU 35, @202, KC0[CB0:0-32], KC1[] ; CM-NEXT: MEM_RAT_CACHELESS STORE_DWORD T0, T1.X ; CM-NEXT: CF_END ; CM-NEXT: PAD @@ -2305,224 +2293,220 @@ define amdgpu_kernel void @s_exp_v4f32(ptr addrspace(1) %out, <4 x float> %in) { ; CM-NEXT: 1069064192(1.442383e+00), 0(0.000000e+00) ; CM-NEXT: MULADD_IEEE T0.X, T0.W, literal.x, PV.W, ; CM-NEXT: ADD T0.Y, T0.Z, -PV.Z, -; CM-NEXT: MUL_IEEE T0.Z, PV.Y, literal.x, -; CM-NEXT: MUL_IEEE * T0.W, T2.W, literal.y, BS:VEC_120/SCL_212 +; CM-NEXT: MUL_IEEE T0.Z, T2.W, literal.y, BS:VEC_120/SCL_212 +; CM-NEXT: MUL_IEEE * T0.W, PV.Y, literal.x, ; CM-NEXT: 967029397(3.122284e-04), 1069064192(1.442383e+00) ; CM-NEXT: TRUNC T1.X, T1.Z, -; CM-NEXT: RNDNE T2.Y, PV.W, -; CM-NEXT: MULADD_IEEE T0.Z, T1.Y, literal.x, PV.Z, -; CM-NEXT: ADD * T1.W, PV.Y, PV.X, +; CM-NEXT: MULADD_IEEE T1.Y, T1.Y, literal.x, PV.W, +; CM-NEXT: RNDNE T1.Z, PV.Z, +; CM-NEXT: ADD * T0.W, PV.Y, PV.X, ; CM-NEXT: 1069064192(1.442383e+00), 0(0.000000e+00) +; CM-NEXT: EXP_IEEE T0.X, T0.W, +; CM-NEXT: EXP_IEEE T0.Y (MASKED), T0.W, +; CM-NEXT: EXP_IEEE T0.Z (MASKED), T0.W, +; CM-NEXT: EXP_IEEE * T0.W (MASKED), T0.W, +; CM-NEXT: TRUNC T2.X, T1.Z, +; CM-NEXT: MULADD_IEEE T0.Y, T2.W, literal.x, T1.Y, +; CM-NEXT: FLT_TO_INT T2.Z, T1.X, +; CM-NEXT: MUL_IEEE * T0.W, PV.X, literal.y, +; CM-NEXT: 967029397(3.122284e-04), 209715200(1.972152e-31) +; CM-NEXT: ADD T1.X, T0.Z, -T1.Z, +; CM-NEXT: MUL_IEEE T1.Y, PV.W, literal.x, +; CM-NEXT: MAX_INT T0.Z, PV.Z, literal.y, +; CM-NEXT: MIN_INT * T1.W, PV.Z, literal.z, +; CM-NEXT: 209715200(1.972152e-31), -330(nan) +; CM-NEXT: 381(5.338947e-43), 0(0.000000e+00) +; CM-NEXT: ADD_INT T3.X, PV.W, literal.x, +; CM-NEXT: ADD_INT T2.Y, PV.Z, literal.y, +; CM-NEXT: ADD_INT T0.Z, T2.Z, literal.z, +; CM-NEXT: SETGT_UINT * T1.W, T2.Z, literal.w, +; CM-NEXT: -254(nan), 204(2.858649e-43) +; CM-NEXT: 102(1.429324e-43), -229(nan) +; CM-NEXT: ADD_INT T4.X, T2.Z, literal.x, +; CM-NEXT: SETGT_UINT T3.Y, T2.Z, literal.y, +; CM-NEXT: CNDE_INT T0.Z, PV.W, PV.Y, PV.Z, +; CM-NEXT: SETGT_INT * T2.W, T2.Z, literal.x, +; CM-NEXT: -127(nan), 254(3.559298e-43) +; CM-NEXT: MUL_IEEE T5.X, T0.X, literal.x, +; CM-NEXT: CNDE_INT T2.Y, PV.W, PV.Z, T2.Z, +; CM-NEXT: CNDE_INT T0.Z, PV.Y, PV.X, T3.X, +; CM-NEXT: SETGT_INT * T3.W, T2.Z, literal.y, +; CM-NEXT: 2130706432(1.701412e+38), 127(1.779649e-43) +; CM-NEXT: AND_INT T3.X, KC0[3].Z, literal.x, +; CM-NEXT: CNDE_INT T2.Y, PV.W, PV.Y, PV.Z, +; CM-NEXT: MUL_IEEE T0.Z, PV.X, literal.y, +; CM-NEXT: CNDE_INT * T0.W, T1.W, T1.Y, T0.W, +; CM-NEXT: -4096(nan), 2130706432(1.701412e+38) +; CM-NEXT: CNDE_INT T0.X, T2.W, PV.W, T0.X, +; CM-NEXT: CNDE_INT T1.Y, T3.Y, T5.X, PV.Z, +; CM-NEXT: LSHL T0.Z, PV.Y, literal.x, +; CM-NEXT: MUL_IEEE * T0.W, PV.X, literal.y, +; CM-NEXT: 23(3.222986e-44), 1069064192(1.442383e+00) +; CM-NEXT: RNDNE T4.X, PV.W, +; CM-NEXT: ADD_INT T2.Y, PV.Z, literal.x, +; CM-NEXT: CNDE_INT T0.Z, T3.W, PV.X, PV.Y, +; CM-NEXT: ADD * T1.W, T1.X, T0.Y, +; CM-NEXT: 1065353216(1.000000e+00), 0(0.000000e+00) ; CM-NEXT: EXP_IEEE T0.X, T1.W, ; CM-NEXT: EXP_IEEE T0.Y (MASKED), T1.W, ; CM-NEXT: EXP_IEEE T0.Z (MASKED), T1.W, ; CM-NEXT: EXP_IEEE * T0.W (MASKED), T1.W, -; CM-NEXT: MULADD_IEEE T2.X, T2.W, literal.x, T0.Z, -; CM-NEXT: ADD T0.Y, T0.W, -T2.Y, BS:VEC_120/SCL_212 -; CM-NEXT: FLT_TO_INT T0.Z, T1.X, -; CM-NEXT: MUL_IEEE * T0.W, PV.X, literal.y, -; CM-NEXT: 967029397(3.122284e-04), 209715200(1.972152e-31) -; CM-NEXT: MUL_IEEE T1.X, PV.W, literal.x, +; CM-NEXT: MUL_IEEE T1.X, T0.Z, T2.Y, +; CM-NEXT: TRUNC T0.Y, T4.X, +; CM-NEXT: FLT_TO_INT T0.Z, T2.X, BS:VEC_120/SCL_212 +; CM-NEXT: MUL_IEEE * T1.W, PV.X, literal.x, +; CM-NEXT: 209715200(1.972152e-31), 0(0.000000e+00) +; CM-NEXT: MUL_IEEE T2.X, PV.W, literal.x, ; CM-NEXT: MUL_IEEE T1.Y, T0.X, literal.y, ; CM-NEXT: MAX_INT T1.Z, PV.Z, literal.z, -; CM-NEXT: MIN_INT * T1.W, PV.Z, literal.w, +; CM-NEXT: MIN_INT * T2.W, PV.Z, literal.w, ; CM-NEXT: 209715200(1.972152e-31), 2130706432(1.701412e+38) ; CM-NEXT: -330(nan), 381(5.338947e-43) -; CM-NEXT: ADD_INT T3.X, PV.W, literal.x, -; CM-NEXT: ADD_INT T3.Y, PV.Z, literal.y, +; CM-NEXT: ADD_INT T5.X, PV.W, literal.x, +; CM-NEXT: ADD_INT T2.Y, PV.Z, literal.y, ; CM-NEXT: ADD_INT T1.Z, T0.Z, literal.z, -; CM-NEXT: SETGT_UINT * T1.W, T0.Z, literal.w, +; CM-NEXT: SETGT_UINT * T2.W, T0.Z, literal.w, ; CM-NEXT: -254(nan), 204(2.858649e-43) ; CM-NEXT: 102(1.429324e-43), -229(nan) -; CM-NEXT: ADD_INT T4.X, T0.Z, literal.x, -; CM-NEXT: SETGT_UINT T4.Y, T0.Z, literal.y, +; CM-NEXT: ADD_INT T6.X, T0.Z, literal.x, +; CM-NEXT: SETGT_UINT T3.Y, T0.Z, literal.y, ; CM-NEXT: CNDE_INT T1.Z, PV.W, PV.Y, PV.Z, -; CM-NEXT: SETGT_INT * T2.W, T0.Z, literal.x, +; CM-NEXT: SETGT_INT * T3.W, T0.Z, literal.x, ; CM-NEXT: -127(nan), 254(3.559298e-43) -; CM-NEXT: CNDE_INT T5.X, PV.W, PV.Z, T0.Z, -; CM-NEXT: CNDE_INT T3.Y, PV.Y, PV.X, T3.X, -; CM-NEXT: SETGT_INT T0.Z, T0.Z, literal.x, -; CM-NEXT: MUL_IEEE * T3.W, T1.Y, literal.y, -; CM-NEXT: 127(1.779649e-43), 2130706432(1.701412e+38) -; CM-NEXT: CNDE_INT T3.X, T4.Y, T1.Y, PV.W, -; CM-NEXT: AND_INT T1.Y, KC0[3].Z, literal.x, -; CM-NEXT: CNDE_INT T1.Z, PV.Z, PV.X, PV.Y, -; CM-NEXT: CNDE_INT * T0.W, T1.W, T1.X, T0.W, -; CM-NEXT: -4096(nan), 0(0.000000e+00) -; CM-NEXT: CNDE_INT T0.X, T2.W, PV.W, T0.X, -; CM-NEXT: LSHL T3.Y, PV.Z, literal.x, -; CM-NEXT: TRUNC T1.Z, T2.Y, -; CM-NEXT: ADD * T0.W, KC0[3].Z, -PV.Y, -; CM-NEXT: 23(3.222986e-44), 0(0.000000e+00) -; CM-NEXT: MUL_IEEE T1.X, PV.W, literal.x, -; CM-NEXT: FLT_TO_INT T2.Y, PV.Z, -; CM-NEXT: ADD_INT T1.Z, PV.Y, literal.y, -; CM-NEXT: CNDE_INT * T1.W, T0.Z, PV.X, T3.X, -; CM-NEXT: 967029397(3.122284e-04), 1065353216(1.000000e+00) -; CM-NEXT: MUL_IEEE T0.X, PV.W, PV.Z, -; CM-NEXT: MIN_INT T3.Y, PV.Y, literal.x, -; CM-NEXT: MULADD_IEEE T0.Z, T0.W, literal.y, PV.X, -; CM-NEXT: ADD * T0.W, T0.Y, T2.X, -; CM-NEXT: 381(5.338947e-43), 1069064192(1.442383e+00) -; CM-NEXT: EXP_IEEE T0.X (MASKED), T0.W, -; CM-NEXT: EXP_IEEE T0.Y, T0.W, -; CM-NEXT: EXP_IEEE T0.Z (MASKED), T0.W, -; CM-NEXT: EXP_IEEE * T0.W (MASKED), T0.W, -; CM-NEXT: MULADD_IEEE T1.X, T1.Y, literal.x, T0.Z, -; CM-NEXT: MUL_IEEE T4.Y, PV.Y, literal.y, -; CM-NEXT: ADD_INT T0.Z, T3.Y, literal.z, BS:VEC_120/SCL_212 -; CM-NEXT: MAX_INT * T0.W, T2.Y, literal.w, BS:VEC_201 -; CM-NEXT: 967029397(3.122284e-04), 2130706432(1.701412e+38) -; CM-NEXT: -254(nan), -330(nan) -; CM-NEXT: ADD_INT T2.X, T2.Y, literal.x, -; CM-NEXT: ADD_INT T3.Y, PV.W, literal.y, -; CM-NEXT: ADD_INT T1.Z, T2.Y, literal.z, -; CM-NEXT: SETGT_UINT * T0.W, T2.Y, literal.w, -; CM-NEXT: -127(nan), 204(2.858649e-43) -; CM-NEXT: 102(1.429324e-43), -229(nan) -; CM-NEXT: SETGT_UINT T3.X, T2.Y, literal.x, -; CM-NEXT: CNDE_INT T3.Y, PV.W, PV.Y, PV.Z, -; CM-NEXT: SETGT_INT T1.Z, T2.Y, literal.y, -; CM-NEXT: MUL_IEEE * T1.W, T0.Y, literal.z, BS:VEC_120/SCL_212 -; CM-NEXT: 254(3.559298e-43), -127(nan) -; CM-NEXT: 209715200(1.972152e-31), 0(0.000000e+00) -; CM-NEXT: MUL_IEEE T4.X, PV.W, literal.x, -; CM-NEXT: CNDE_INT * T3.Y, PV.Z, PV.Y, T2.Y, -; CM-NEXT: 209715200(1.972152e-31), 0(0.000000e+00) -; CM-NEXT: ALU clause starting at 104: -; CM-NEXT: CNDE_INT T0.Z, T3.X, T2.X, T0.Z, -; CM-NEXT: SETGT_INT * T2.W, T2.Y, literal.x, +; CM-NEXT: CNDE_INT T7.X, PV.W, PV.Z, T0.Z, +; CM-NEXT: CNDE_INT T2.Y, PV.Y, PV.X, T5.X, +; CM-NEXT: SETGT_INT * T0.Z, T0.Z, literal.x, ; CM-NEXT: 127(1.779649e-43), 0(0.000000e+00) -; CM-NEXT: MUL_IEEE T2.X, T1.Y, literal.x, -; CM-NEXT: CNDE_INT T1.Y, PV.W, T3.Y, PV.Z, -; CM-NEXT: CNDE_INT T0.Z, T0.W, T4.X, T1.W, -; CM-NEXT: MUL_IEEE * T0.W, T4.Y, literal.y, BS:VEC_201 -; CM-NEXT: 1069064192(1.442383e+00), 2130706432(1.701412e+38) -; CM-NEXT: AND_INT T4.X, KC0[4].X, literal.x, -; CM-NEXT: CNDE_INT T2.Y, T3.X, T4.Y, PV.W, -; CM-NEXT: CNDE_INT T0.Z, T1.Z, PV.Z, T0.Y, -; CM-NEXT: LSHL * T0.W, PV.Y, literal.y, -; CM-NEXT: -4096(nan), 23(3.222986e-44) -; CM-NEXT: ADD_INT T3.X, PV.W, literal.x, -; CM-NEXT: CNDE_INT T0.Y, T2.W, PV.Z, PV.Y, -; CM-NEXT: MUL_IEEE T0.Z, PV.X, literal.y, -; CM-NEXT: RNDNE * T0.W, T2.X, -; CM-NEXT: 1065353216(1.000000e+00), 1069064192(1.442383e+00) -; CM-NEXT: ADD T2.X, T2.X, -PV.W, -; CM-NEXT: RNDNE T1.Y, PV.Z, -; CM-NEXT: MUL_IEEE T1.Z, PV.Y, PV.X, -; CM-NEXT: SETGT * T1.W, literal.x, KC0[3].W, -; CM-NEXT: -1026650416(-1.032789e+02), 0(0.000000e+00) -; CM-NEXT: CNDE T3.X, PV.W, PV.Z, 0.0, -; CM-NEXT: TRUNC T0.Y, T0.W, -; CM-NEXT: TRUNC T1.Z, PV.Y, -; CM-NEXT: ADD * T0.W, PV.X, T1.X, +; CM-NEXT: ALU clause starting at 104: +; CM-NEXT: ADD * T4.W, KC0[3].Z, -T3.X, +; CM-NEXT: MUL_IEEE T5.X, PV.W, literal.x, +; CM-NEXT: CNDE_INT T2.Y, T0.Z, T7.X, T2.Y, +; CM-NEXT: MUL_IEEE T1.Z, T1.Y, literal.y, +; CM-NEXT: CNDE_INT * T1.W, T2.W, T2.X, T1.W, BS:VEC_021/SCL_122 +; CM-NEXT: 967029397(3.122284e-04), 2130706432(1.701412e+38) +; CM-NEXT: CNDE_INT T0.X, T3.W, PV.W, T0.X, +; CM-NEXT: CNDE_INT T1.Y, T3.Y, T1.Y, PV.Z, +; CM-NEXT: LSHL T1.Z, PV.Y, literal.x, +; CM-NEXT: MULADD_IEEE * T1.W, T4.W, literal.y, PV.X, BS:VEC_120/SCL_212 +; CM-NEXT: 23(3.222986e-44), 1069064192(1.442383e+00) +; CM-NEXT: MULADD_IEEE T2.X, T3.X, literal.x, PV.W, +; CM-NEXT: ADD T2.Y, T0.W, -T4.X, +; CM-NEXT: ADD_INT T1.Z, PV.Z, literal.y, +; CM-NEXT: CNDE_INT * T0.W, T0.Z, PV.X, PV.Y, +; CM-NEXT: 967029397(3.122284e-04), 1065353216(1.000000e+00) +; CM-NEXT: AND_INT T0.X, KC0[4].X, literal.x, +; CM-NEXT: MUL_IEEE T1.Y, PV.W, PV.Z, +; CM-NEXT: SETGT T0.Z, literal.y, KC0[3].W, +; CM-NEXT: ADD * T0.W, PV.Y, PV.X, +; CM-NEXT: -4096(nan), -1026650416(-1.032789e+02) ; CM-NEXT: EXP_IEEE T0.X (MASKED), T0.W, ; CM-NEXT: EXP_IEEE T0.Y (MASKED), T0.W, ; CM-NEXT: EXP_IEEE T0.Z (MASKED), T0.W, ; CM-NEXT: EXP_IEEE * T0.W, T0.W, -; CM-NEXT: FLT_TO_INT T1.X, T1.Z, -; CM-NEXT: FLT_TO_INT T0.Y, T0.Y, -; CM-NEXT: MUL_IEEE T1.Z, PV.W, literal.x, -; CM-NEXT: ADD * T1.W, KC0[4].X, -T4.X, -; CM-NEXT: 2130706432(1.701412e+38), 0(0.000000e+00) -; CM-NEXT: MUL_IEEE T2.X, PV.W, literal.x, -; CM-NEXT: MUL_IEEE T2.Y, T0.W, literal.y, -; CM-NEXT: MUL_IEEE T2.Z, PV.Z, literal.z, -; CM-NEXT: SETGT_UINT * T2.W, PV.Y, literal.w, -; CM-NEXT: 967029397(3.122284e-04), 209715200(1.972152e-31) -; CM-NEXT: 2130706432(1.701412e+38), 254(3.559298e-43) -; CM-NEXT: CNDE_INT T5.X, PV.W, T1.Z, PV.Z, -; CM-NEXT: MUL_IEEE T3.Y, PV.Y, literal.x, -; CM-NEXT: MULADD_IEEE T1.Z, T1.W, literal.y, PV.X, -; CM-NEXT: MAX_INT * T1.W, T1.X, literal.z, -; CM-NEXT: 209715200(1.972152e-31), 1069064192(1.442383e+00) -; CM-NEXT: -330(nan), 0(0.000000e+00) -; CM-NEXT: ADD_INT T2.X, PV.W, literal.x, -; CM-NEXT: ADD_INT T4.Y, T1.X, literal.y, -; CM-NEXT: MULADD_IEEE T1.Z, T4.X, literal.z, PV.Z, BS:VEC_120/SCL_212 -; CM-NEXT: MAX_INT * T1.W, T0.Y, literal.w, -; CM-NEXT: 204(2.858649e-43), 102(1.429324e-43) +; CM-NEXT: CNDE T2.X, T0.Z, T1.Y, 0.0, +; CM-NEXT: ADD T1.Y, KC0[4].X, -T0.X, +; CM-NEXT: FLT_TO_INT T0.Z, T0.Y, +; CM-NEXT: MUL_IEEE * T1.W, PV.W, literal.x, +; CM-NEXT: 209715200(1.972152e-31), 0(0.000000e+00) +; CM-NEXT: MUL_IEEE T3.X, PV.W, literal.x, +; CM-NEXT: SETGT_UINT T0.Y, PV.Z, literal.y, +; CM-NEXT: MUL_IEEE T1.Z, PV.Y, literal.z, +; CM-NEXT: MUL_IEEE * T2.W, T0.X, literal.w, +; CM-NEXT: 209715200(1.972152e-31), -229(nan) +; CM-NEXT: 967029397(3.122284e-04), 1069064192(1.442383e+00) +; CM-NEXT: RNDNE T4.X, PV.W, +; CM-NEXT: MULADD_IEEE T1.Y, T1.Y, literal.x, PV.Z, +; CM-NEXT: CNDE_INT T1.Z, PV.Y, PV.X, T1.W, +; CM-NEXT: SETGT_INT * T1.W, T0.Z, literal.y, +; CM-NEXT: 1069064192(1.442383e+00), -127(nan) +; CM-NEXT: CNDE_INT T3.X, PV.W, PV.Z, T0.W, +; CM-NEXT: MULADD_IEEE T1.Y, T0.X, literal.x, PV.Y, +; CM-NEXT: ADD T1.Z, T2.W, -PV.X, +; CM-NEXT: MAX_INT * T2.W, T0.Z, literal.y, ; CM-NEXT: 967029397(3.122284e-04), -330(nan) -; CM-NEXT: ADD T4.X, T0.Z, -T1.Y, -; CM-NEXT: ADD_INT T1.Y, PV.W, literal.x, -; CM-NEXT: ADD_INT T0.Z, T0.Y, literal.y, -; CM-NEXT: SETGT_UINT * T1.W, T0.Y, literal.z, +; CM-NEXT: ADD_INT T0.X, PV.W, literal.x, +; CM-NEXT: ADD_INT T2.Y, T0.Z, literal.y, +; CM-NEXT: TRUNC T2.Z, T4.X, +; CM-NEXT: ADD * T2.W, PV.Z, PV.Y, ; CM-NEXT: 204(2.858649e-43), 102(1.429324e-43) -; CM-NEXT: -229(nan), 0(0.000000e+00) -; CM-NEXT: SETGT_UINT T6.X, T1.X, literal.x, -; CM-NEXT: CNDE_INT T1.Y, PV.W, PV.Y, PV.Z, -; CM-NEXT: SETGT_INT T0.Z, T0.Y, literal.y, -; CM-NEXT: ADD * T3.W, PV.X, T1.Z, -; CM-NEXT: -229(nan), -127(nan) -; CM-NEXT: EXP_IEEE T1.X (MASKED), T3.W, -; CM-NEXT: EXP_IEEE T1.Y (MASKED), T3.W, -; CM-NEXT: EXP_IEEE T1.Z, T3.W, -; CM-NEXT: EXP_IEEE * T1.W (MASKED), T3.W, -; CM-NEXT: CNDE_INT T4.X, T0.Z, T1.Y, T0.Y, -; CM-NEXT: CNDE_INT T1.Y, T6.X, T2.X, T4.Y, BS:VEC_120/SCL_212 -; CM-NEXT: SETGT_INT T2.Z, T1.X, literal.x, -; CM-NEXT: MUL_IEEE * T3.W, PV.Z, literal.y, -; CM-NEXT: -127(nan), 209715200(1.972152e-31) -; CM-NEXT: MUL_IEEE T2.X, T1.Z, literal.x, -; CM-NEXT: MUL_IEEE T4.Y, PV.W, literal.y, -; CM-NEXT: CNDE_INT T3.Z, PV.Z, PV.Y, T1.X, -; CM-NEXT: MIN_INT * T4.W, T1.X, literal.z, +; CM-NEXT: EXP_IEEE T1.X (MASKED), T2.W, +; CM-NEXT: EXP_IEEE T1.Y, T2.W, +; CM-NEXT: EXP_IEEE T1.Z (MASKED), T2.W, +; CM-NEXT: EXP_IEEE * T1.W (MASKED), T2.W, +; CM-NEXT: MUL_IEEE T4.X, T0.W, literal.x, +; CM-NEXT: FLT_TO_INT T3.Y, T2.Z, +; CM-NEXT: MUL_IEEE T1.Z, PV.Y, literal.y, +; CM-NEXT: CNDE_INT * T0.W, T0.Y, T0.X, T2.Y, ; CM-NEXT: 2130706432(1.701412e+38), 209715200(1.972152e-31) +; CM-NEXT: CNDE_INT T0.X, T1.W, PV.W, T0.Z, +; CM-NEXT: MUL_IEEE T0.Y, PV.Z, literal.x, +; CM-NEXT: MAX_INT T2.Z, PV.Y, literal.y, +; CM-NEXT: MIN_INT * T0.W, PV.Y, literal.z, +; CM-NEXT: 209715200(1.972152e-31), -330(nan) ; CM-NEXT: 381(5.338947e-43), 0(0.000000e+00) -; CM-NEXT: MIN_INT T7.X, T0.Y, literal.x, -; CM-NEXT: ADD_INT T1.Y, PV.W, literal.y, -; CM-NEXT: ADD_INT T4.Z, T1.X, literal.z, -; CM-NEXT: SETGT_UINT * T4.W, T1.X, literal.w, -; CM-NEXT: 381(5.338947e-43), -254(nan) +; CM-NEXT: ADD_INT T5.X, PV.W, literal.x, +; CM-NEXT: ADD_INT T2.Y, PV.Z, literal.y, +; CM-NEXT: ADD_INT T2.Z, T3.Y, literal.z, +; CM-NEXT: SETGT_UINT * T0.W, T3.Y, literal.w, +; CM-NEXT: -254(nan), 204(2.858649e-43) +; CM-NEXT: 102(1.429324e-43), -229(nan) +; CM-NEXT: ADD_INT T6.X, T3.Y, literal.x, +; CM-NEXT: SETGT_UINT T4.Y, T3.Y, literal.y, +; CM-NEXT: CNDE_INT T2.Z, PV.W, PV.Y, PV.Z, +; CM-NEXT: SETGT_INT * T1.W, T3.Y, literal.x, ; CM-NEXT: -127(nan), 254(3.559298e-43) -; CM-NEXT: CNDE_INT T8.X, PV.W, PV.Z, PV.Y, -; CM-NEXT: SETGT_INT T1.Y, T1.X, literal.x, -; CM-NEXT: ADD_INT T4.Z, PV.X, literal.y, -; CM-NEXT: ADD_INT * T5.W, T0.Y, literal.z, +; CM-NEXT: MUL_IEEE T7.X, T1.Y, literal.x, +; CM-NEXT: CNDE_INT T2.Y, PV.W, PV.Z, T3.Y, +; CM-NEXT: CNDE_INT T2.Z, PV.Y, PV.X, T5.X, +; CM-NEXT: MIN_INT * T2.W, T0.Z, literal.y, +; CM-NEXT: 2130706432(1.701412e+38), 381(5.338947e-43) +; CM-NEXT: SETGT_INT T5.X, T3.Y, literal.x, +; CM-NEXT: ADD_INT T3.Y, PV.W, literal.y, +; CM-NEXT: ADD_INT T3.Z, T0.Z, literal.z, +; CM-NEXT: SETGT_UINT * T2.W, T0.Z, literal.w, ; CM-NEXT: 127(1.779649e-43), -254(nan) -; CM-NEXT: -127(nan), 0(0.000000e+00) -; CM-NEXT: CNDE_INT T1.X, T2.W, PV.W, PV.Z, -; CM-NEXT: CNDE_INT T5.Y, PV.Y, T3.Z, PV.X, -; CM-NEXT: CNDE_INT T3.Z, T6.X, T4.Y, T3.W, -; CM-NEXT: MUL_IEEE * T2.W, T2.X, literal.x, BS:VEC_120/SCL_212 +; CM-NEXT: -127(nan), 254(3.559298e-43) +; CM-NEXT: CNDE_INT T6.X, PV.W, PV.Z, PV.Y, +; CM-NEXT: CNDE_INT T2.Y, PV.X, T2.Y, T2.Z, +; CM-NEXT: MUL_IEEE T2.Z, T7.X, literal.x, +; CM-NEXT: CNDE_INT * T0.W, T0.W, T0.Y, T1.Z, BS:VEC_021/SCL_122 ; CM-NEXT: 2130706432(1.701412e+38), 0(0.000000e+00) -; CM-NEXT: SETGT_INT T6.X, T0.Y, literal.x, -; CM-NEXT: CNDE_INT T0.Y, T4.W, T2.X, PV.W, -; CM-NEXT: CNDE_INT * T1.Z, T2.Z, PV.Z, T1.Z, -; CM-NEXT: 127(1.779649e-43), 0(0.000000e+00) -; CM-NEXT: ALU clause starting at 205: -; CM-NEXT: LSHL * T2.W, T5.Y, literal.x, -; CM-NEXT: 23(3.222986e-44), 0(0.000000e+00) -; CM-NEXT: ADD_INT T2.X, PV.W, literal.x, -; CM-NEXT: CNDE_INT T0.Y, T1.Y, T1.Z, T0.Y, -; CM-NEXT: CNDE_INT * T1.Z, T6.X, T4.X, T1.X, +; CM-NEXT: SETGT_INT T8.X, T0.Z, literal.x, +; CM-NEXT: CNDE_INT T0.Y, T1.W, PV.W, T1.Y, +; CM-NEXT: CNDE_INT T0.Z, T4.Y, T7.X, PV.Z, +; CM-NEXT: LSHL * T0.W, PV.Y, literal.y, +; CM-NEXT: 127(1.779649e-43), 23(3.222986e-44) +; CM-NEXT: ALU clause starting at 202: +; CM-NEXT: ADD_INT T7.X, T0.W, literal.x, +; CM-NEXT: CNDE_INT * T0.Y, T5.X, T0.Y, T0.Z, ; CM-NEXT: 1065353216(1.000000e+00), 0(0.000000e+00) -; CM-NEXT: CNDE_INT * T1.W, T1.W, T3.Y, T2.Y, -; CM-NEXT: CNDE_INT T1.X, T0.Z, PV.W, T0.W, -; CM-NEXT: LSHL T1.Y, T1.Z, literal.x, BS:VEC_120/SCL_212 -; CM-NEXT: MUL_IEEE T0.Z, T0.Y, T2.X, +; CM-NEXT: CNDE_INT * T0.Z, T8.X, T0.X, T6.X, +; CM-NEXT: MUL_IEEE * T0.W, T4.X, literal.x, +; CM-NEXT: 2130706432(1.701412e+38), 0(0.000000e+00) +; CM-NEXT: CNDE_INT T0.X, T2.W, T4.X, PV.W, +; CM-NEXT: LSHL T1.Y, T0.Z, literal.x, +; CM-NEXT: MUL_IEEE T0.Z, T0.Y, T7.X, BS:VEC_021/SCL_122 ; CM-NEXT: SETGT * T0.W, literal.y, KC0[4].X, ; CM-NEXT: 23(3.222986e-44), -1026650416(-1.032789e+02) -; CM-NEXT: CNDE T2.X, PV.W, PV.Z, 0.0, +; CM-NEXT: CNDE T4.X, PV.W, PV.Z, 0.0, ; CM-NEXT: SETGT T0.Y, KC0[4].X, literal.x, ; CM-NEXT: ADD_INT T0.Z, PV.Y, literal.y, -; CM-NEXT: CNDE_INT * T0.W, T6.X, PV.X, T5.X, +; CM-NEXT: CNDE_INT * T0.W, T8.X, T3.X, PV.X, ; CM-NEXT: 1118925336(8.872284e+01), 1065353216(1.000000e+00) -; CM-NEXT: SETGT T1.X, KC0[3].W, literal.x, +; CM-NEXT: SETGT T0.X, KC0[3].W, literal.x, ; CM-NEXT: MUL_IEEE T1.Y, PV.W, PV.Z, ; CM-NEXT: SETGT T0.Z, literal.y, KC0[3].Z, ; CM-NEXT: CNDE * T0.W, PV.Y, PV.X, literal.z, ; CM-NEXT: 1118925336(8.872284e+01), -1026650416(-1.032789e+02) ; CM-NEXT: 2139095040(INF), 0(0.000000e+00) -; CM-NEXT: SETGT T2.X, literal.x, KC0[3].Y, +; CM-NEXT: SETGT T3.X, literal.x, KC0[3].Y, ; CM-NEXT: CNDE T0.Y, PV.Z, PV.Y, 0.0, -; CM-NEXT: CNDE T0.Z, PV.X, T3.X, literal.y, +; CM-NEXT: CNDE T0.Z, PV.X, T2.X, literal.y, ; CM-NEXT: SETGT * T1.W, KC0[3].Z, literal.z, ; CM-NEXT: -1026650416(-1.032789e+02), 2139095040(INF) ; CM-NEXT: 1118925336(8.872284e+01), 0(0.000000e+00) ; CM-NEXT: CNDE T0.Y, PV.W, PV.Y, literal.x, -; CM-NEXT: CNDE T1.Z, PV.X, T0.X, 0.0, +; CM-NEXT: CNDE T1.Z, PV.X, T1.X, 0.0, ; CM-NEXT: SETGT * T1.W, KC0[3].Y, literal.y, ; CM-NEXT: 2139095040(INF), 1118925336(8.872284e+01) ; CM-NEXT: CNDE * T0.X, PV.W, PV.Z, literal.x, diff --git a/llvm/test/CodeGen/AMDGPU/llvm.exp10.ll b/llvm/test/CodeGen/AMDGPU/llvm.exp10.ll index 544c1de6c7bb..a16294958748 100644 --- a/llvm/test/CodeGen/AMDGPU/llvm.exp10.ll +++ b/llvm/test/CodeGen/AMDGPU/llvm.exp10.ll @@ -230,23 +230,23 @@ define amdgpu_kernel void @s_exp10_f32(ptr addrspace(1) %out, float %in) { ; R600-NEXT: MUL_IEEE * T2.W, PS, literal.z, ; R600-NEXT: -127(nan), 254(3.559298e-43) ; R600-NEXT: 209715200(1.972152e-31), 0(0.000000e+00) -; R600-NEXT: MUL_IEEE T3.X, T1.X, literal.x, -; R600-NEXT: MUL_IEEE T0.Y, PS, literal.y, +; R600-NEXT: MUL_IEEE T3.X, PS, literal.x, +; R600-NEXT: MUL_IEEE T0.Y, T1.X, literal.y, ; R600-NEXT: CNDE_INT T1.Z, PV.W, PV.Z, T0.Z, ; R600-NEXT: CNDE_INT T3.W, PV.Y, PV.X, T0.X, ; R600-NEXT: SETGT_INT * T4.W, T0.Z, literal.z, -; R600-NEXT: 2130706432(1.701412e+38), 209715200(1.972152e-31) +; R600-NEXT: 209715200(1.972152e-31), 2130706432(1.701412e+38) ; R600-NEXT: 127(1.779649e-43), 0(0.000000e+00) ; R600-NEXT: CNDE_INT T0.Z, PS, PV.Z, PV.W, -; R600-NEXT: CNDE_INT T0.W, T0.W, PV.Y, T2.W, -; R600-NEXT: MUL_IEEE * T2.W, PV.X, literal.x, +; R600-NEXT: MUL_IEEE T3.W, PV.Y, literal.x, +; R600-NEXT: CNDE_INT * T0.W, T0.W, PV.X, T2.W, ; R600-NEXT: 2130706432(1.701412e+38), 0(0.000000e+00) -; R600-NEXT: CNDE_INT T1.Z, T1.Y, T3.X, PS, -; R600-NEXT: CNDE_INT T0.W, T1.W, PV.W, T1.X, +; R600-NEXT: CNDE_INT T1.Z, T1.W, PS, T1.X, +; R600-NEXT: CNDE_INT T0.W, T1.Y, T0.Y, PV.W, ; R600-NEXT: LSHL * T1.W, PV.Z, literal.x, ; R600-NEXT: 23(3.222986e-44), 0(0.000000e+00) ; R600-NEXT: ADD_INT T1.W, PS, literal.x, -; R600-NEXT: CNDE_INT * T0.W, T4.W, PV.W, PV.Z, +; R600-NEXT: CNDE_INT * T0.W, T4.W, PV.Z, PV.W, ; R600-NEXT: 1065353216(1.000000e+00), 0(0.000000e+00) ; R600-NEXT: MUL_IEEE T0.W, PS, PV.W, ; R600-NEXT: SETGT * T1.W, literal.x, KC0[2].Z, @@ -260,65 +260,63 @@ define amdgpu_kernel void @s_exp10_f32(ptr addrspace(1) %out, float %in) { ; ; CM-LABEL: s_exp10_f32: ; CM: ; %bb.0: -; CM-NEXT: ALU 64, @4, KC0[CB0:0-32], KC1[] +; CM-NEXT: ALU 62, @4, KC0[CB0:0-32], KC1[] ; CM-NEXT: MEM_RAT_CACHELESS STORE_DWORD T0.X, T1.X ; CM-NEXT: CF_END ; CM-NEXT: PAD ; CM-NEXT: ALU clause starting at 4: ; CM-NEXT: AND_INT * T0.W, KC0[2].Z, literal.x, ; CM-NEXT: -4096(nan), 0(0.000000e+00) -; CM-NEXT: MUL_IEEE T0.Z, PV.W, literal.x, ; CM-NEXT: ADD * T1.W, KC0[2].Z, -PV.W, -; CM-NEXT: 1079283712(3.321289e+00), 0(0.000000e+00) -; CM-NEXT: MUL_IEEE T1.Z, PV.W, literal.x, -; CM-NEXT: RNDNE * T2.W, PV.Z, -; CM-NEXT: 975668412(6.390323e-04), 0(0.000000e+00) -; CM-NEXT: TRUNC T2.Z, PV.W, +; CM-NEXT: MUL_IEEE T0.Z, PV.W, literal.x, +; CM-NEXT: MUL_IEEE * T2.W, T0.W, literal.y, +; CM-NEXT: 975668412(6.390323e-04), 1079283712(3.321289e+00) +; CM-NEXT: RNDNE T1.Z, PV.W, ; CM-NEXT: MULADD_IEEE * T1.W, T1.W, literal.x, PV.Z, ; CM-NEXT: 1079283712(3.321289e+00), 0(0.000000e+00) -; CM-NEXT: MULADD_IEEE T0.Y, T0.W, literal.x, PV.W, -; CM-NEXT: ADD T0.Z, T0.Z, -T2.W, -; CM-NEXT: FLT_TO_INT * T0.W, PV.Z, +; CM-NEXT: MULADD_IEEE T0.Z, T0.W, literal.x, PV.W, +; CM-NEXT: ADD * T0.W, T2.W, -PV.Z, BS:VEC_120/SCL_212 ; CM-NEXT: 975668412(6.390323e-04), 0(0.000000e+00) -; CM-NEXT: MIN_INT T1.Z, PV.W, literal.x, -; CM-NEXT: ADD * T1.W, PV.Z, PV.Y, +; CM-NEXT: TRUNC T1.Z, T1.Z, +; CM-NEXT: ADD * T0.W, PV.W, PV.Z, +; CM-NEXT: EXP_IEEE T0.X, T0.W, +; CM-NEXT: EXP_IEEE T0.Y (MASKED), T0.W, +; CM-NEXT: EXP_IEEE T0.Z (MASKED), T0.W, +; CM-NEXT: EXP_IEEE * T0.W (MASKED), T0.W, +; CM-NEXT: FLT_TO_INT T0.Z, T1.Z, +; CM-NEXT: MUL_IEEE * T0.W, PV.X, literal.x, +; CM-NEXT: 209715200(1.972152e-31), 0(0.000000e+00) +; CM-NEXT: MUL_IEEE T0.Y, PV.W, literal.x, +; CM-NEXT: MAX_INT T1.Z, PV.Z, literal.y, +; CM-NEXT: MIN_INT * T1.W, PV.Z, literal.z, +; CM-NEXT: 209715200(1.972152e-31), -330(nan) ; CM-NEXT: 381(5.338947e-43), 0(0.000000e+00) -; CM-NEXT: EXP_IEEE T0.X, T1.W, -; CM-NEXT: EXP_IEEE T0.Y (MASKED), T1.W, -; CM-NEXT: EXP_IEEE T0.Z (MASKED), T1.W, -; CM-NEXT: EXP_IEEE * T0.W (MASKED), T1.W, -; CM-NEXT: MUL_IEEE T0.Y, PV.X, literal.x, -; CM-NEXT: ADD_INT T0.Z, T1.Z, literal.y, -; CM-NEXT: MAX_INT * T1.W, T0.W, literal.z, -; CM-NEXT: 2130706432(1.701412e+38), -254(nan) -; CM-NEXT: -330(nan), 0(0.000000e+00) -; CM-NEXT: ADD_INT T1.X, T0.W, literal.x, -; CM-NEXT: ADD_INT T1.Y, PV.W, literal.y, -; CM-NEXT: ADD_INT T1.Z, T0.W, literal.z, -; CM-NEXT: SETGT_UINT * T1.W, T0.W, literal.w, -; CM-NEXT: -127(nan), 204(2.858649e-43) +; CM-NEXT: ADD_INT T1.X, PV.W, literal.x, +; CM-NEXT: ADD_INT T1.Y, PV.Z, literal.y, +; CM-NEXT: ADD_INT T1.Z, T0.Z, literal.z, +; CM-NEXT: SETGT_UINT * T1.W, T0.Z, literal.w, +; CM-NEXT: -254(nan), 204(2.858649e-43) ; CM-NEXT: 102(1.429324e-43), -229(nan) -; CM-NEXT: SETGT_UINT T2.X, T0.W, literal.x, -; CM-NEXT: CNDE_INT T1.Y, PV.W, PV.Y, PV.Z, -; CM-NEXT: SETGT_INT T1.Z, T0.W, literal.y, -; CM-NEXT: MUL_IEEE * T2.W, T0.X, literal.z, -; CM-NEXT: 254(3.559298e-43), -127(nan) -; CM-NEXT: 209715200(1.972152e-31), 0(0.000000e+00) -; CM-NEXT: MUL_IEEE T3.X, PV.W, literal.x, -; CM-NEXT: CNDE_INT T1.Y, PV.Z, PV.Y, T0.W, -; CM-NEXT: CNDE_INT T0.Z, PV.X, T1.X, T0.Z, -; CM-NEXT: SETGT_INT * T0.W, T0.W, literal.y, -; CM-NEXT: 209715200(1.972152e-31), 127(1.779649e-43) +; CM-NEXT: ADD_INT T2.X, T0.Z, literal.x, +; CM-NEXT: SETGT_UINT T2.Y, T0.Z, literal.y, +; CM-NEXT: CNDE_INT T1.Z, PV.W, PV.Y, PV.Z, +; CM-NEXT: SETGT_INT * T2.W, T0.Z, literal.x, +; CM-NEXT: -127(nan), 254(3.559298e-43) +; CM-NEXT: MUL_IEEE T3.X, T0.X, literal.x, +; CM-NEXT: CNDE_INT T1.Y, PV.W, PV.Z, T0.Z, +; CM-NEXT: CNDE_INT T1.Z, PV.Y, PV.X, T1.X, +; CM-NEXT: SETGT_INT * T3.W, T0.Z, literal.y, +; CM-NEXT: 2130706432(1.701412e+38), 127(1.779649e-43) ; CM-NEXT: CNDE_INT T1.Y, PV.W, PV.Y, PV.Z, -; CM-NEXT: CNDE_INT T0.Z, T1.W, PV.X, T2.W, -; CM-NEXT: MUL_IEEE * T1.W, T0.Y, literal.x, +; CM-NEXT: MUL_IEEE T0.Z, PV.X, literal.x, +; CM-NEXT: CNDE_INT * T0.W, T1.W, T0.Y, T0.W, ; CM-NEXT: 2130706432(1.701412e+38), 0(0.000000e+00) -; CM-NEXT: CNDE_INT T0.Y, T2.X, T0.Y, PV.W, -; CM-NEXT: CNDE_INT T0.Z, T1.Z, PV.Z, T0.X, -; CM-NEXT: LSHL * T1.W, PV.Y, literal.x, +; CM-NEXT: CNDE_INT T0.Y, T2.W, PV.W, T0.X, +; CM-NEXT: CNDE_INT T0.Z, T2.Y, T3.X, PV.Z, +; CM-NEXT: LSHL * T0.W, PV.Y, literal.x, ; CM-NEXT: 23(3.222986e-44), 0(0.000000e+00) ; CM-NEXT: ADD_INT T1.Z, PV.W, literal.x, -; CM-NEXT: CNDE_INT * T0.W, T0.W, PV.Z, PV.Y, +; CM-NEXT: CNDE_INT * T0.W, T3.W, PV.Y, PV.Z, ; CM-NEXT: 1065353216(1.000000e+00), 0(0.000000e+00) ; CM-NEXT: MUL_IEEE T0.Z, PV.W, PV.Z, ; CM-NEXT: SETGT * T0.W, literal.x, KC0[2].Z, @@ -612,105 +610,105 @@ define amdgpu_kernel void @s_exp10_v2f32(ptr addrspace(1) %out, <2 x float> %in) ; R600-NEXT: AND_INT * T0.W, KC0[3].X, literal.x, ; R600-NEXT: -4096(nan), 0(0.000000e+00) ; R600-NEXT: ADD * T1.W, KC0[3].X, -PV.W, -; R600-NEXT: AND_INT T0.Z, KC0[2].W, literal.x, -; R600-NEXT: MUL_IEEE T2.W, PV.W, literal.y, -; R600-NEXT: MUL_IEEE * T3.W, T0.W, literal.z, -; R600-NEXT: -4096(nan), 975668412(6.390323e-04) -; R600-NEXT: 1079283712(3.321289e+00), 0(0.000000e+00) -; R600-NEXT: RNDNE T1.Z, PS, +; R600-NEXT: MUL_IEEE T2.W, PV.W, literal.x, +; R600-NEXT: MUL_IEEE * T3.W, T0.W, literal.y, +; R600-NEXT: 975668412(6.390323e-04), 1079283712(3.321289e+00) +; R600-NEXT: RNDNE T0.Z, PS, ; R600-NEXT: MULADD_IEEE T1.W, T1.W, literal.x, PV.W, -; R600-NEXT: ADD * T2.W, KC0[2].W, -PV.Z, -; R600-NEXT: 1079283712(3.321289e+00), 0(0.000000e+00) -; R600-NEXT: MUL_IEEE T0.Y, PS, literal.x, -; R600-NEXT: MUL_IEEE T2.Z, T0.Z, literal.y, +; R600-NEXT: AND_INT * T2.W, KC0[2].W, literal.y, +; R600-NEXT: 1079283712(3.321289e+00), -4096(nan) +; R600-NEXT: ADD T1.Z, KC0[2].W, -PS, ; R600-NEXT: MULADD_IEEE T0.W, T0.W, literal.x, PV.W, ; R600-NEXT: ADD * T1.W, T3.W, -PV.Z, +; R600-NEXT: 975668412(6.390323e-04), 0(0.000000e+00) +; R600-NEXT: ADD T2.Z, PS, PV.W, +; R600-NEXT: MUL_IEEE T0.W, PV.Z, literal.x, +; R600-NEXT: MUL_IEEE * T1.W, T2.W, literal.y, ; R600-NEXT: 975668412(6.390323e-04), 1079283712(3.321289e+00) -; R600-NEXT: ADD T3.Z, PS, PV.W, -; R600-NEXT: RNDNE T0.W, PV.Z, -; R600-NEXT: MULADD_IEEE * T1.W, T2.W, literal.x, PV.Y, BS:VEC_021/SCL_122 -; R600-NEXT: 1079283712(3.321289e+00), 0(0.000000e+00) -; R600-NEXT: TRUNC T0.Y, T1.Z, -; R600-NEXT: MULADD_IEEE T0.Z, T0.Z, literal.x, PS, BS:VEC_120/SCL_212 -; R600-NEXT: ADD T1.W, T2.Z, -PV.W, BS:VEC_201 +; R600-NEXT: RNDNE T0.Y, PS, +; R600-NEXT: MULADD_IEEE T1.Z, T1.Z, literal.x, PV.W, +; R600-NEXT: TRUNC T0.W, T0.Z, BS:VEC_120/SCL_212 ; R600-NEXT: EXP_IEEE * T0.X, PV.Z, -; R600-NEXT: 975668412(6.390323e-04), 0(0.000000e+00) -; R600-NEXT: ADD T0.Z, PV.W, PV.Z, -; R600-NEXT: FLT_TO_INT T1.W, PV.Y, -; R600-NEXT: MUL_IEEE * T2.W, PS, literal.x, -; R600-NEXT: 2130706432(1.701412e+38), 0(0.000000e+00) -; R600-NEXT: MUL_IEEE T1.Z, PS, literal.x, -; R600-NEXT: SETGT_UINT T3.W, PV.W, literal.y, -; R600-NEXT: EXP_IEEE * T0.Y, PV.Z, -; R600-NEXT: 2130706432(1.701412e+38), 254(3.559298e-43) -; R600-NEXT: CNDE_INT T1.X, PV.W, T2.W, PV.Z, -; R600-NEXT: MUL_IEEE T1.Y, PS, literal.x, -; R600-NEXT: MAX_INT T0.Z, T1.W, literal.y, -; R600-NEXT: MIN_INT T2.W, T1.W, literal.z, -; R600-NEXT: TRUNC * T0.W, T0.W, +; R600-NEXT: 1079283712(3.321289e+00), 0(0.000000e+00) +; R600-NEXT: FLT_TO_INT T1.Y, PV.W, +; R600-NEXT: MUL_IEEE T0.Z, PS, literal.x, +; R600-NEXT: MULADD_IEEE T0.W, T2.W, literal.y, PV.Z, +; R600-NEXT: ADD * T1.W, T1.W, -PV.Y, +; R600-NEXT: 209715200(1.972152e-31), 975668412(6.390323e-04) +; R600-NEXT: ADD T1.Z, PS, PV.W, +; R600-NEXT: MUL_IEEE T0.W, PV.Z, literal.x, +; R600-NEXT: SETGT_UINT * T1.W, PV.Y, literal.y, +; R600-NEXT: 209715200(1.972152e-31), -229(nan) +; R600-NEXT: CNDE_INT T0.Z, PS, PV.W, T0.Z, +; R600-NEXT: SETGT_INT T0.W, T1.Y, literal.x, +; R600-NEXT: EXP_IEEE * T1.X, PV.Z, +; R600-NEXT: -127(nan), 0(0.000000e+00) +; R600-NEXT: CNDE_INT T0.Z, PV.W, PV.Z, T0.X, +; R600-NEXT: MAX_INT T2.W, T1.Y, literal.x, +; R600-NEXT: MUL_IEEE * T3.W, PS, literal.y, +; R600-NEXT: -330(nan), 209715200(1.972152e-31) +; R600-NEXT: MUL_IEEE T2.X, PS, literal.x, +; R600-NEXT: ADD_INT T2.Y, PV.W, literal.y, +; R600-NEXT: ADD_INT T1.Z, T1.Y, literal.z, +; R600-NEXT: MIN_INT T2.W, T1.Y, literal.w, +; R600-NEXT: TRUNC * T4.W, T0.Y, +; R600-NEXT: 209715200(1.972152e-31), 204(2.858649e-43) +; R600-NEXT: 102(1.429324e-43), 381(5.338947e-43) +; R600-NEXT: FLT_TO_INT T3.X, PS, +; R600-NEXT: ADD_INT T0.Y, PV.W, literal.x, +; R600-NEXT: ADD_INT T2.Z, T1.Y, literal.y, +; R600-NEXT: SETGT_UINT T2.W, T1.Y, literal.z, +; R600-NEXT: CNDE_INT * T1.W, T1.W, PV.Y, PV.Z, +; R600-NEXT: -254(nan), -127(nan) +; R600-NEXT: 254(3.559298e-43), 0(0.000000e+00) +; R600-NEXT: MUL_IEEE T4.X, T1.X, literal.x, +; R600-NEXT: MUL_IEEE T2.Y, T0.X, literal.x, BS:VEC_120/SCL_212 +; R600-NEXT: CNDE_INT T1.Z, T0.W, PS, T1.Y, +; R600-NEXT: CNDE_INT T0.W, PV.W, PV.Z, PV.Y, +; R600-NEXT: MAX_INT * T1.W, PV.X, literal.y, ; R600-NEXT: 2130706432(1.701412e+38), -330(nan) -; R600-NEXT: 381(5.338947e-43), 0(0.000000e+00) -; R600-NEXT: FLT_TO_INT T2.X, PS, -; R600-NEXT: ADD_INT T2.Y, PV.W, literal.x, -; R600-NEXT: ADD_INT T0.Z, PV.Z, literal.y, -; R600-NEXT: ADD_INT T0.W, T1.W, literal.z, -; R600-NEXT: SETGT_UINT * T2.W, T1.W, literal.w, -; R600-NEXT: -254(nan), 204(2.858649e-43) -; R600-NEXT: 102(1.429324e-43), -229(nan) -; R600-NEXT: ADD_INT T3.X, T1.W, literal.x, -; R600-NEXT: CNDE_INT T3.Y, PS, PV.Z, PV.W, -; R600-NEXT: SETGT_INT T0.Z, T1.W, literal.x, -; R600-NEXT: MUL_IEEE T0.W, T0.X, literal.y, -; R600-NEXT: MUL_IEEE * T4.W, T0.Y, literal.y, -; R600-NEXT: -127(nan), 209715200(1.972152e-31) -; R600-NEXT: MUL_IEEE T4.X, PS, literal.x, -; R600-NEXT: MUL_IEEE T4.Y, PV.W, literal.x, -; R600-NEXT: CNDE_INT T1.Z, PV.Z, PV.Y, T1.W, -; R600-NEXT: CNDE_INT T3.W, T3.W, PV.X, T2.Y, -; R600-NEXT: MAX_INT * T5.W, T2.X, literal.y, -; R600-NEXT: 209715200(1.972152e-31), -330(nan) -; R600-NEXT: SETGT_INT T3.X, T1.W, literal.x, -; R600-NEXT: ADD_INT T2.Y, PS, literal.y, -; R600-NEXT: ADD_INT T2.Z, T2.X, literal.z, -; R600-NEXT: SETGT_UINT * T1.W, T2.X, literal.w, +; R600-NEXT: SETGT_INT T0.X, T1.Y, literal.x, +; R600-NEXT: ADD_INT T0.Y, PS, literal.y, +; R600-NEXT: ADD_INT T2.Z, T3.X, literal.z, +; R600-NEXT: SETGT_UINT * T1.W, T3.X, literal.w, ; R600-NEXT: 127(1.779649e-43), 204(2.858649e-43) ; R600-NEXT: 102(1.429324e-43), -229(nan) -; R600-NEXT: MIN_INT * T5.W, T2.X, literal.x, +; R600-NEXT: MIN_INT * T4.W, T3.X, literal.x, ; R600-NEXT: 381(5.338947e-43), 0(0.000000e+00) ; R600-NEXT: ADD_INT T5.X, PV.W, literal.x, -; R600-NEXT: ADD_INT T3.Y, T2.X, literal.y, -; R600-NEXT: SETGT_UINT T3.Z, T2.X, literal.z, -; R600-NEXT: CNDE_INT T5.W, T1.W, T2.Y, T2.Z, -; R600-NEXT: SETGT_INT * T6.W, T2.X, literal.y, +; R600-NEXT: ADD_INT T1.Y, T3.X, literal.y, +; R600-NEXT: SETGT_UINT T3.Z, T3.X, literal.z, +; R600-NEXT: CNDE_INT T4.W, T1.W, T0.Y, T2.Z, +; R600-NEXT: SETGT_INT * T5.W, T3.X, literal.y, ; R600-NEXT: -254(nan), -127(nan) ; R600-NEXT: 254(3.559298e-43), 0(0.000000e+00) -; R600-NEXT: CNDE_INT T6.X, PS, PV.W, T2.X, -; R600-NEXT: CNDE_INT T2.Y, PV.Z, PV.Y, PV.X, -; R600-NEXT: SETGT_INT T2.Z, T2.X, literal.x, BS:VEC_120/SCL_212 -; R600-NEXT: CNDE_INT T3.W, T3.X, T1.Z, T3.W, BS:VEC_021/SCL_122 -; R600-NEXT: CNDE_INT * T0.W, T2.W, T4.Y, T0.W, -; R600-NEXT: 127(1.779649e-43), 0(0.000000e+00) -; R600-NEXT: CNDE_INT T0.X, T0.Z, PS, T0.X, -; R600-NEXT: LSHL T3.Y, PV.W, literal.x, -; R600-NEXT: CNDE_INT T0.Z, PV.Z, PV.X, PV.Y, -; R600-NEXT: CNDE_INT T0.W, T1.W, T4.X, T4.W, -; R600-NEXT: MUL_IEEE * T1.W, T1.Y, literal.y, +; R600-NEXT: CNDE_INT T6.X, PS, PV.W, T3.X, +; R600-NEXT: CNDE_INT T0.Y, PV.Z, PV.Y, PV.X, +; R600-NEXT: SETGT_INT T2.Z, T3.X, literal.x, +; R600-NEXT: CNDE_INT T0.W, T0.X, T1.Z, T0.W, BS:VEC_120/SCL_212 +; R600-NEXT: MUL_IEEE * T4.W, T2.Y, literal.y, +; R600-NEXT: 127(1.779649e-43), 2130706432(1.701412e+38) +; R600-NEXT: CNDE_INT T3.X, T2.W, T2.Y, PS, BS:VEC_120/SCL_212 +; R600-NEXT: LSHL T1.Y, PV.W, literal.x, +; R600-NEXT: CNDE_INT T1.Z, PV.Z, PV.X, PV.Y, +; R600-NEXT: MUL_IEEE T0.W, T4.X, literal.y, +; R600-NEXT: CNDE_INT * T1.W, T1.W, T2.X, T3.W, ; R600-NEXT: 23(3.222986e-44), 2130706432(1.701412e+38) -; R600-NEXT: CNDE_INT T2.X, T3.Z, T1.Y, PS, -; R600-NEXT: CNDE_INT T0.Y, T6.W, PV.W, T0.Y, -; R600-NEXT: LSHL T0.Z, PV.Z, literal.x, +; R600-NEXT: CNDE_INT T1.X, T5.W, PS, T1.X, BS:VEC_021/SCL_122 +; R600-NEXT: CNDE_INT T0.Y, T3.Z, T4.X, PV.W, BS:VEC_201 +; R600-NEXT: LSHL T1.Z, PV.Z, literal.x, ; R600-NEXT: ADD_INT T0.W, PV.Y, literal.y, -; R600-NEXT: CNDE_INT * T1.W, T3.X, PV.X, T1.X, +; R600-NEXT: CNDE_INT * T1.W, T0.X, T0.Z, PV.X, ; R600-NEXT: 23(3.222986e-44), 1065353216(1.000000e+00) ; R600-NEXT: MUL_IEEE T1.Y, PS, PV.W, -; R600-NEXT: SETGT T1.Z, literal.x, KC0[3].X, +; R600-NEXT: SETGT T0.Z, literal.x, KC0[3].X, ; R600-NEXT: ADD_INT * T0.W, PV.Z, literal.y, ; R600-NEXT: -1036817932(-4.485347e+01), 1065353216(1.000000e+00) ; R600-NEXT: ALU clause starting at 101: -; R600-NEXT: CNDE_INT * T1.W, T2.Z, T0.Y, T2.X, +; R600-NEXT: CNDE_INT * T1.W, T2.Z, T1.X, T0.Y, ; R600-NEXT: MUL_IEEE T0.Y, PV.W, T0.W, -; R600-NEXT: SETGT T0.Z, literal.x, KC0[2].W, -; R600-NEXT: CNDE T0.W, T1.Z, T1.Y, 0.0, +; R600-NEXT: SETGT T1.Z, literal.x, KC0[2].W, +; R600-NEXT: CNDE T0.W, T0.Z, T1.Y, 0.0, ; R600-NEXT: SETGT * T1.W, KC0[3].X, literal.y, ; R600-NEXT: -1036817932(-4.485347e+01), 1109008539(3.853184e+01) ; R600-NEXT: CNDE T1.Y, PS, PV.W, literal.x, @@ -723,118 +721,116 @@ define amdgpu_kernel void @s_exp10_v2f32(ptr addrspace(1) %out, <2 x float> %in) ; ; CM-LABEL: s_exp10_v2f32: ; CM: ; %bb.0: -; CM-NEXT: ALU 100, @4, KC0[CB0:0-32], KC1[] -; CM-NEXT: ALU 18, @105, KC0[CB0:0-32], KC1[] +; CM-NEXT: ALU 98, @4, KC0[CB0:0-32], KC1[] +; CM-NEXT: ALU 18, @103, KC0[CB0:0-32], KC1[] ; CM-NEXT: MEM_RAT_CACHELESS STORE_DWORD T0, T1.X ; CM-NEXT: CF_END ; CM-NEXT: ALU clause starting at 4: ; CM-NEXT: AND_INT * T0.W, KC0[2].W, literal.x, ; CM-NEXT: -4096(nan), 0(0.000000e+00) -; CM-NEXT: MUL_IEEE T0.Z, PV.W, literal.x, ; CM-NEXT: ADD * T1.W, KC0[2].W, -PV.W, +; CM-NEXT: MUL_IEEE T0.Y, PV.W, literal.x, +; CM-NEXT: MUL_IEEE T0.Z, T0.W, literal.y, +; CM-NEXT: AND_INT * T2.W, KC0[3].X, literal.z, +; CM-NEXT: 975668412(6.390323e-04), 1079283712(3.321289e+00) +; CM-NEXT: -4096(nan), 0(0.000000e+00) +; CM-NEXT: ADD T1.Y, KC0[3].X, -PV.W, +; CM-NEXT: RNDNE T1.Z, PV.Z, +; CM-NEXT: MULADD_IEEE * T1.W, T1.W, literal.x, PV.Y, ; CM-NEXT: 1079283712(3.321289e+00), 0(0.000000e+00) -; CM-NEXT: MUL_IEEE T1.Z, PV.W, literal.x, -; CM-NEXT: RNDNE * T2.W, PV.Z, -; CM-NEXT: 975668412(6.390323e-04), 0(0.000000e+00) -; CM-NEXT: TRUNC T0.Y, PV.W, -; CM-NEXT: AND_INT T2.Z, KC0[3].X, literal.x, -; CM-NEXT: MULADD_IEEE * T1.W, T1.W, literal.y, PV.Z, -; CM-NEXT: -4096(nan), 1079283712(3.321289e+00) ; CM-NEXT: MULADD_IEEE T0.X, T0.W, literal.x, PV.W, -; CM-NEXT: MUL_IEEE T1.Y, PV.Z, literal.y, -; CM-NEXT: FLT_TO_INT T1.Z, PV.Y, -; CM-NEXT: ADD * T0.W, KC0[3].X, -PV.Z, +; CM-NEXT: ADD T0.Y, T0.Z, -PV.Z, +; CM-NEXT: MUL_IEEE T0.Z, PV.Y, literal.x, +; CM-NEXT: MUL_IEEE * T0.W, T2.W, literal.y, BS:VEC_120/SCL_212 ; CM-NEXT: 975668412(6.390323e-04), 1079283712(3.321289e+00) -; CM-NEXT: ADD T1.X, T0.Z, -T2.W, -; CM-NEXT: MUL_IEEE T0.Y, PV.W, literal.x, -; CM-NEXT: MAX_INT T0.Z, PV.Z, literal.y, -; CM-NEXT: RNDNE * T1.W, PV.Y, -; CM-NEXT: 975668412(6.390323e-04), -330(nan) -; CM-NEXT: TRUNC T2.X, PV.W, -; CM-NEXT: ADD_INT T2.Y, PV.Z, literal.x, -; CM-NEXT: MULADD_IEEE T0.Z, T0.W, literal.y, PV.Y, -; CM-NEXT: ADD * T0.W, PV.X, T0.X, -; CM-NEXT: 204(2.858649e-43), 1079283712(3.321289e+00) -; CM-NEXT: EXP_IEEE T0.X, T0.W, -; CM-NEXT: EXP_IEEE T0.Y (MASKED), T0.W, -; CM-NEXT: EXP_IEEE T0.Z (MASKED), T0.W, -; CM-NEXT: EXP_IEEE * T0.W (MASKED), T0.W, -; CM-NEXT: ADD_INT T1.X, T1.Z, literal.x, -; CM-NEXT: MULADD_IEEE T0.Y, T2.Z, literal.y, T0.Z, BS:VEC_102/SCL_221 -; CM-NEXT: ADD T0.Z, T1.Y, -T1.W, -; CM-NEXT: MUL_IEEE * T0.W, PV.X, literal.z, -; CM-NEXT: 102(1.429324e-43), 975668412(6.390323e-04) -; CM-NEXT: 2130706432(1.701412e+38), 0(0.000000e+00) -; CM-NEXT: SETGT_UINT T3.X, T1.Z, literal.x, -; CM-NEXT: MUL_IEEE T1.Y, PV.W, literal.y, -; CM-NEXT: SETGT_UINT T2.Z, T1.Z, literal.z, -; CM-NEXT: ADD * T1.W, PV.Z, PV.Y, -; CM-NEXT: -229(nan), 2130706432(1.701412e+38) -; CM-NEXT: 254(3.559298e-43), 0(0.000000e+00) +; CM-NEXT: TRUNC T1.X, T1.Z, +; CM-NEXT: RNDNE T2.Y, PV.W, +; CM-NEXT: MULADD_IEEE T0.Z, T1.Y, literal.x, PV.Z, +; CM-NEXT: ADD * T1.W, PV.Y, PV.X, +; CM-NEXT: 1079283712(3.321289e+00), 0(0.000000e+00) +; CM-NEXT: EXP_IEEE T0.X, T1.W, +; CM-NEXT: EXP_IEEE T0.Y (MASKED), T1.W, +; CM-NEXT: EXP_IEEE T0.Z (MASKED), T1.W, +; CM-NEXT: EXP_IEEE * T0.W (MASKED), T1.W, +; CM-NEXT: MULADD_IEEE T2.X, T2.W, literal.x, T0.Z, +; CM-NEXT: ADD T0.Y, T0.W, -T2.Y, BS:VEC_120/SCL_212 +; CM-NEXT: FLT_TO_INT T0.Z, T1.X, +; CM-NEXT: MUL_IEEE * T0.W, PV.X, literal.y, +; CM-NEXT: 975668412(6.390323e-04), 209715200(1.972152e-31) +; CM-NEXT: MUL_IEEE T1.X, PV.W, literal.x, +; CM-NEXT: SETGT_UINT T1.Y, PV.Z, literal.y, +; CM-NEXT: TRUNC T1.Z, T2.Y, +; CM-NEXT: ADD * T1.W, PV.Y, PV.X, +; CM-NEXT: 209715200(1.972152e-31), -229(nan) ; CM-NEXT: EXP_IEEE T0.X (MASKED), T1.W, ; CM-NEXT: EXP_IEEE T0.Y, T1.W, ; CM-NEXT: EXP_IEEE T0.Z (MASKED), T1.W, ; CM-NEXT: EXP_IEEE * T0.W (MASKED), T1.W, -; CM-NEXT: CNDE_INT T4.X, T2.Z, T0.W, T1.Y, -; CM-NEXT: CNDE_INT T1.Y, T3.X, T2.Y, T1.X, -; CM-NEXT: FLT_TO_INT T0.Z, T2.X, BS:VEC_120/SCL_212 -; CM-NEXT: MUL_IEEE * T0.W, PV.Y, literal.x, -; CM-NEXT: 2130706432(1.701412e+38), 0(0.000000e+00) -; CM-NEXT: SETGT_INT T1.X, T1.Z, literal.x, -; CM-NEXT: MUL_IEEE T2.Y, T0.X, literal.y, -; CM-NEXT: MUL_IEEE T3.Z, PV.W, literal.z, -; CM-NEXT: SETGT_UINT * T1.W, PV.Z, literal.w, -; CM-NEXT: -127(nan), 209715200(1.972152e-31) -; CM-NEXT: 2130706432(1.701412e+38), 254(3.559298e-43) -; CM-NEXT: CNDE_INT T2.X, PV.W, T0.W, PV.Z, +; CM-NEXT: FLT_TO_INT T2.X, T1.Z, +; CM-NEXT: MUL_IEEE T2.Y, PV.Y, literal.x, +; CM-NEXT: CNDE_INT T1.Z, T1.Y, T1.X, T0.W, +; CM-NEXT: SETGT_INT * T0.W, T0.Z, literal.y, BS:VEC_120/SCL_212 +; CM-NEXT: 209715200(1.972152e-31), -127(nan) +; CM-NEXT: CNDE_INT T1.X, PV.W, PV.Z, T0.X, ; CM-NEXT: MUL_IEEE T3.Y, PV.Y, literal.x, -; CM-NEXT: CNDE_INT T3.Z, PV.X, T1.Y, T1.Z, -; CM-NEXT: MAX_INT * T0.W, T0.Z, literal.y, -; CM-NEXT: 209715200(1.972152e-31), -330(nan) -; CM-NEXT: ADD_INT T5.X, PV.W, literal.x, -; CM-NEXT: ADD_INT T1.Y, T0.Z, literal.y, -; CM-NEXT: SETGT_UINT T4.Z, T0.Z, literal.z, -; CM-NEXT: MUL_IEEE * T0.W, T0.Y, literal.w, +; CM-NEXT: SETGT_UINT T1.Z, PV.X, literal.y, +; CM-NEXT: MAX_INT * T1.W, T0.Z, literal.z, +; CM-NEXT: 209715200(1.972152e-31), -229(nan) +; CM-NEXT: -330(nan), 0(0.000000e+00) +; CM-NEXT: ADD_INT T3.X, PV.W, literal.x, +; CM-NEXT: ADD_INT T4.Y, T0.Z, literal.y, +; CM-NEXT: CNDE_INT T2.Z, PV.Z, PV.Y, T2.Y, +; CM-NEXT: SETGT_INT * T1.W, T2.X, literal.z, ; CM-NEXT: 204(2.858649e-43), 102(1.429324e-43) -; CM-NEXT: -229(nan), 209715200(1.972152e-31) -; CM-NEXT: MUL_IEEE T6.X, PV.W, literal.x, -; CM-NEXT: MIN_INT T4.Y, T0.Z, literal.y, -; CM-NEXT: CNDE_INT T5.Z, PV.Z, PV.X, PV.Y, -; CM-NEXT: SETGT_INT * T2.W, T0.Z, literal.z, -; CM-NEXT: 209715200(1.972152e-31), 381(5.338947e-43) -; CM-NEXT: -127(nan), 0(0.000000e+00) -; CM-NEXT: CNDE_INT T5.X, PV.W, PV.Z, T0.Z, -; CM-NEXT: MIN_INT T1.Y, T1.Z, literal.x, -; CM-NEXT: ADD_INT T5.Z, PV.Y, literal.y, -; CM-NEXT: ADD_INT * T3.W, T0.Z, literal.z, BS:VEC_120/SCL_212 -; CM-NEXT: 381(5.338947e-43), -254(nan) ; CM-NEXT: -127(nan), 0(0.000000e+00) -; CM-NEXT: CNDE_INT T7.X, T1.W, PV.W, PV.Z, -; CM-NEXT: SETGT_INT T4.Y, T0.Z, literal.x, -; CM-NEXT: ADD_INT T0.Z, PV.Y, literal.y, -; CM-NEXT: ADD_INT * T1.W, T1.Z, literal.z, BS:VEC_120/SCL_212 +; CM-NEXT: CNDE_INT T4.X, PV.W, PV.Z, T0.Y, +; CM-NEXT: MUL_IEEE T2.Y, T0.X, literal.x, +; CM-NEXT: MAX_INT T2.Z, T2.X, literal.y, BS:VEC_120/SCL_212 +; CM-NEXT: CNDE_INT * T2.W, T1.Y, PV.X, PV.Y, +; CM-NEXT: 2130706432(1.701412e+38), -330(nan) +; CM-NEXT: CNDE_INT T0.X, T0.W, PV.W, T0.Z, +; CM-NEXT: ADD_INT T1.Y, PV.Z, literal.x, +; CM-NEXT: ADD_INT T2.Z, T2.X, literal.y, +; CM-NEXT: MIN_INT * T0.W, T2.X, literal.z, +; CM-NEXT: 204(2.858649e-43), 102(1.429324e-43) +; CM-NEXT: 381(5.338947e-43), 0(0.000000e+00) +; CM-NEXT: ADD_INT T3.X, PV.W, literal.x, +; CM-NEXT: ADD_INT T3.Y, T2.X, literal.y, +; CM-NEXT: SETGT_UINT T3.Z, T2.X, literal.z, +; CM-NEXT: CNDE_INT * T0.W, T1.Z, PV.Y, PV.Z, +; CM-NEXT: -254(nan), -127(nan) +; CM-NEXT: 254(3.559298e-43), 0(0.000000e+00) +; CM-NEXT: MUL_IEEE T5.X, T0.Y, literal.x, +; CM-NEXT: CNDE_INT T0.Y, T1.W, PV.W, T2.X, +; CM-NEXT: CNDE_INT T1.Z, PV.Z, PV.Y, PV.X, +; CM-NEXT: MIN_INT * T0.W, T0.Z, literal.y, +; CM-NEXT: 2130706432(1.701412e+38), 381(5.338947e-43) +; CM-NEXT: SETGT_INT T2.X, T2.X, literal.x, +; CM-NEXT: ADD_INT T1.Y, PV.W, literal.y, +; CM-NEXT: ADD_INT T2.Z, T0.Z, literal.z, +; CM-NEXT: SETGT_UINT * T0.W, T0.Z, literal.w, ; CM-NEXT: 127(1.779649e-43), -254(nan) -; CM-NEXT: -127(nan), 0(0.000000e+00) -; CM-NEXT: CNDE_INT T8.X, T2.Z, PV.W, PV.Z, -; CM-NEXT: SETGT_INT T1.Y, T1.Z, literal.x, BS:VEC_120/SCL_212 -; CM-NEXT: CNDE_INT T0.Z, PV.Y, T5.X, PV.X, -; CM-NEXT: CNDE_INT * T0.W, T4.Z, T6.X, T0.W, BS:VEC_201 -; CM-NEXT: 127(1.779649e-43), 0(0.000000e+00) -; CM-NEXT: CNDE_INT T5.X, T2.W, PV.W, T0.Y, +; CM-NEXT: -127(nan), 254(3.559298e-43) +; CM-NEXT: CNDE_INT T3.X, PV.W, PV.Z, PV.Y, +; CM-NEXT: SETGT_INT T1.Y, T0.Z, literal.x, +; CM-NEXT: CNDE_INT T0.Z, PV.X, T0.Y, T1.Z, +; CM-NEXT: MUL_IEEE * T1.W, T5.X, literal.y, +; CM-NEXT: 127(1.779649e-43), 2130706432(1.701412e+38) +; CM-NEXT: CNDE_INT T5.X, T3.Z, T5.X, PV.W, ; CM-NEXT: LSHL T0.Y, PV.Z, literal.x, -; CM-NEXT: CNDE_INT T0.Z, PV.Y, T3.Z, PV.X, -; CM-NEXT: CNDE_INT * T0.W, T3.X, T3.Y, T2.Y, BS:VEC_201 -; CM-NEXT: 23(3.222986e-44), 0(0.000000e+00) -; CM-NEXT: CNDE_INT T0.X, T1.X, PV.W, T0.X, +; CM-NEXT: CNDE_INT T0.Z, PV.Y, T0.X, PV.X, BS:VEC_021/SCL_122 +; CM-NEXT: MUL_IEEE * T1.W, T2.Y, literal.y, +; CM-NEXT: 23(3.222986e-44), 2130706432(1.701412e+38) +; CM-NEXT: CNDE_INT T0.X, T0.W, T2.Y, PV.W, ; CM-NEXT: LSHL T2.Y, PV.Z, literal.x, ; CM-NEXT: ADD_INT * T0.Z, PV.Y, literal.y, ; CM-NEXT: 23(3.222986e-44), 1065353216(1.000000e+00) -; CM-NEXT: ALU clause starting at 105: -; CM-NEXT: CNDE_INT * T0.W, T4.Y, T5.X, T2.X, -; CM-NEXT: MUL_IEEE T1.X, PV.W, T0.Z, +; CM-NEXT: ALU clause starting at 103: +; CM-NEXT: CNDE_INT * T0.W, T2.X, T4.X, T5.X, +; CM-NEXT: MUL_IEEE T2.X, PV.W, T0.Z, ; CM-NEXT: SETGT T0.Y, literal.x, KC0[3].X, ; CM-NEXT: ADD_INT T0.Z, T2.Y, literal.y, -; CM-NEXT: CNDE_INT * T0.W, T1.Y, T0.X, T4.X, BS:VEC_120/SCL_212 +; CM-NEXT: CNDE_INT * T0.W, T1.Y, T1.X, T0.X, BS:VEC_120/SCL_212 ; CM-NEXT: -1036817932(-4.485347e+01), 1065353216(1.000000e+00) ; CM-NEXT: MUL_IEEE T0.X, PV.W, PV.Z, ; CM-NEXT: SETGT T1.Y, literal.x, KC0[2].W, @@ -1217,8 +1213,8 @@ define amdgpu_kernel void @s_exp10_v3f32(ptr addrspace(1) %out, <3 x float> %in) ; ; R600-LABEL: s_exp10_v3f32: ; R600: ; %bb.0: -; R600-NEXT: ALU 100, @6, KC0[CB0:0-32], KC1[] -; R600-NEXT: ALU 69, @107, KC0[CB0:0-32], KC1[] +; R600-NEXT: ALU 99, @6, KC0[CB0:0-32], KC1[] +; R600-NEXT: ALU 69, @106, KC0[CB0:0-32], KC1[] ; R600-NEXT: MEM_RAT_CACHELESS STORE_RAW T2.X, T3.X, 0 ; R600-NEXT: MEM_RAT_CACHELESS STORE_RAW T0.XY, T1.X, 1 ; R600-NEXT: CF_END @@ -1226,69 +1222,68 @@ define amdgpu_kernel void @s_exp10_v3f32(ptr addrspace(1) %out, <3 x float> %in) ; R600-NEXT: ALU clause starting at 6: ; R600-NEXT: AND_INT * T0.W, KC0[3].Y, literal.x, ; R600-NEXT: -4096(nan), 0(0.000000e+00) -; R600-NEXT: ADD T1.W, KC0[3].Y, -PV.W, -; R600-NEXT: MUL_IEEE * T2.W, PV.W, literal.x, +; R600-NEXT: MUL_IEEE T1.W, PV.W, literal.x, +; R600-NEXT: ADD * T2.W, KC0[3].Y, -PV.W, ; R600-NEXT: 1079283712(3.321289e+00), 0(0.000000e+00) -; R600-NEXT: RNDNE T3.W, PS, -; R600-NEXT: MUL_IEEE * T4.W, PV.W, literal.x, +; R600-NEXT: RNDNE * T3.W, PV.W, +; R600-NEXT: TRUNC T4.W, PV.W, +; R600-NEXT: MUL_IEEE * T5.W, T2.W, literal.x, ; R600-NEXT: 975668412(6.390323e-04), 0(0.000000e+00) -; R600-NEXT: MULADD_IEEE T1.W, T1.W, literal.x, PS, -; R600-NEXT: TRUNC * T4.W, PV.W, +; R600-NEXT: MULADD_IEEE T2.W, T2.W, literal.x, PS, +; R600-NEXT: FLT_TO_INT * T4.W, PV.W, ; R600-NEXT: 1079283712(3.321289e+00), 0(0.000000e+00) -; R600-NEXT: FLT_TO_INT T0.Z, PS, -; R600-NEXT: MULADD_IEEE T0.W, T0.W, literal.x, PV.W, -; R600-NEXT: ADD * T1.W, T2.W, -T3.W, -; R600-NEXT: 975668412(6.390323e-04), 0(0.000000e+00) -; R600-NEXT: ADD T0.W, PS, PV.W, -; R600-NEXT: MAX_INT * T1.W, PV.Z, literal.x, -; R600-NEXT: -330(nan), 0(0.000000e+00) -; R600-NEXT: ADD_INT T0.Y, PS, literal.x, -; R600-NEXT: ADD_INT T1.Z, T0.Z, literal.y, -; R600-NEXT: SETGT_UINT T1.W, T0.Z, literal.z, -; R600-NEXT: EXP_IEEE * T0.X, PV.W, +; R600-NEXT: MAX_INT T0.Z, PS, literal.x, +; R600-NEXT: MULADD_IEEE T0.W, T0.W, literal.y, PV.W, +; R600-NEXT: ADD * T1.W, T1.W, -T3.W, +; R600-NEXT: -330(nan), 975668412(6.390323e-04) +; R600-NEXT: ADD T0.Y, PS, PV.W, +; R600-NEXT: ADD_INT T0.Z, PV.Z, literal.x, +; R600-NEXT: ADD_INT T0.W, T4.W, literal.y, +; R600-NEXT: SETGT_UINT * T1.W, T4.W, literal.z, ; R600-NEXT: 204(2.858649e-43), 102(1.429324e-43) ; R600-NEXT: -229(nan), 0(0.000000e+00) -; R600-NEXT: CNDE_INT T1.Z, PV.W, PV.Y, PV.Z, -; R600-NEXT: SETGT_INT T0.W, T0.Z, literal.x, -; R600-NEXT: MUL_IEEE * T2.W, PS, literal.y, -; R600-NEXT: -127(nan), 209715200(1.972152e-31) -; R600-NEXT: MUL_IEEE T0.Y, PS, literal.x, -; R600-NEXT: CNDE_INT T1.Z, PV.W, PV.Z, T0.Z, -; R600-NEXT: MIN_INT T3.W, T0.Z, literal.y, -; R600-NEXT: AND_INT * T4.W, KC0[3].W, literal.z, -; R600-NEXT: 209715200(1.972152e-31), 381(5.338947e-43) -; R600-NEXT: -4096(nan), 0(0.000000e+00) -; R600-NEXT: MUL_IEEE T1.X, T0.X, literal.x, -; R600-NEXT: ADD T1.Y, KC0[3].W, -PS, -; R600-NEXT: ADD_INT T2.Z, PV.W, literal.y, -; R600-NEXT: ADD_INT T3.W, T0.Z, literal.z, -; R600-NEXT: SETGT_UINT * T5.W, T0.Z, literal.w, -; R600-NEXT: 2130706432(1.701412e+38), -254(nan) +; R600-NEXT: CNDE_INT T0.Z, PS, PV.Z, PV.W, +; R600-NEXT: SETGT_INT T0.W, T4.W, literal.x, +; R600-NEXT: EXP_IEEE * T0.X, PV.Y, +; R600-NEXT: -127(nan), 0(0.000000e+00) +; R600-NEXT: MUL_IEEE T1.X, PS, literal.x, +; R600-NEXT: CNDE_INT T0.Y, PV.W, PV.Z, T4.W, +; R600-NEXT: MIN_INT T0.Z, T4.W, literal.y, +; R600-NEXT: AND_INT T2.W, KC0[3].W, literal.z, +; R600-NEXT: MUL_IEEE * T3.W, PS, literal.w, +; R600-NEXT: 2130706432(1.701412e+38), 381(5.338947e-43) +; R600-NEXT: -4096(nan), 209715200(1.972152e-31) +; R600-NEXT: MUL_IEEE T2.X, PS, literal.x, +; R600-NEXT: ADD T1.Y, KC0[3].W, -PV.W, +; R600-NEXT: ADD_INT T0.Z, PV.Z, literal.y, +; R600-NEXT: ADD_INT T5.W, T4.W, literal.z, +; R600-NEXT: SETGT_UINT * T6.W, T4.W, literal.w, +; R600-NEXT: 209715200(1.972152e-31), -254(nan) ; R600-NEXT: -127(nan), 254(3.559298e-43) -; R600-NEXT: CNDE_INT T2.X, PS, PV.W, PV.Z, -; R600-NEXT: SETGT_INT T2.Y, T0.Z, literal.x, +; R600-NEXT: CNDE_INT T3.X, PS, PV.W, PV.Z, +; R600-NEXT: SETGT_INT T2.Y, T4.W, literal.x, ; R600-NEXT: MUL_IEEE T0.Z, PV.Y, literal.y, -; R600-NEXT: MUL_IEEE T3.W, T4.W, literal.z, -; R600-NEXT: MUL_IEEE * T6.W, PV.X, literal.w, +; R600-NEXT: MUL_IEEE * T4.W, T2.W, literal.z, BS:VEC_120/SCL_212 ; R600-NEXT: 127(1.779649e-43), 975668412(6.390323e-04) -; R600-NEXT: 1079283712(3.321289e+00), 2130706432(1.701412e+38) -; R600-NEXT: CNDE_INT T1.X, T5.W, T1.X, PS, BS:VEC_120/SCL_212 -; R600-NEXT: RNDNE T3.Y, PV.W, -; R600-NEXT: MULADD_IEEE T0.Z, T1.Y, literal.x, PV.Z, -; R600-NEXT: CNDE_INT T5.W, PV.Y, T1.Z, PV.X, -; R600-NEXT: CNDE_INT * T1.W, T1.W, T0.Y, T2.W, ; R600-NEXT: 1079283712(3.321289e+00), 0(0.000000e+00) -; R600-NEXT: CNDE_INT T0.X, T0.W, PS, T0.X, +; R600-NEXT: CNDE_INT * T1.W, T1.W, T2.X, T3.W, +; R600-NEXT: CNDE_INT T0.X, T0.W, PV.W, T0.X, BS:VEC_021/SCL_122 +; R600-NEXT: RNDNE T3.Y, T4.W, BS:VEC_120/SCL_212 +; R600-NEXT: MULADD_IEEE T0.Z, T1.Y, literal.x, T0.Z, +; R600-NEXT: CNDE_INT T0.W, T2.Y, T0.Y, T3.X, BS:VEC_120/SCL_212 +; R600-NEXT: MUL_IEEE * T1.W, T1.X, literal.y, +; R600-NEXT: 1079283712(3.321289e+00), 2130706432(1.701412e+38) +; R600-NEXT: CNDE_INT T1.X, T6.W, T1.X, PS, ; R600-NEXT: LSHL T0.Y, PV.W, literal.x, ; R600-NEXT: AND_INT T1.Z, KC0[3].Z, literal.y, -; R600-NEXT: MULADD_IEEE T0.W, T4.W, literal.z, PV.Z, BS:VEC_120/SCL_212 -; R600-NEXT: ADD * T1.W, T3.W, -PV.Y, +; R600-NEXT: MULADD_IEEE T0.W, T2.W, literal.z, PV.Z, BS:VEC_120/SCL_212 +; R600-NEXT: ADD * T1.W, T4.W, -PV.Y, ; R600-NEXT: 23(3.222986e-44), -4096(nan) ; R600-NEXT: 975668412(6.390323e-04), 0(0.000000e+00) ; R600-NEXT: ADD T1.Y, PS, PV.W, ; R600-NEXT: MUL_IEEE T0.Z, PV.Z, literal.x, ; R600-NEXT: ADD_INT T0.W, PV.Y, literal.y, -; R600-NEXT: CNDE_INT * T1.W, T2.Y, PV.X, T1.X, +; R600-NEXT: CNDE_INT * T1.W, T2.Y, T0.X, PV.X, ; R600-NEXT: 1079283712(3.321289e+00), 1065353216(1.000000e+00) ; R600-NEXT: MUL_IEEE T0.X, PS, PV.W, ; R600-NEXT: ADD T0.Y, KC0[3].Z, -T1.Z, @@ -1302,12 +1297,12 @@ define amdgpu_kernel void @s_exp10_v3f32(ptr addrspace(1) %out, <3 x float> %in) ; R600-NEXT: MUL_IEEE * T1.W, PS, literal.z, ; R600-NEXT: -1036817932(-4.485347e+01), 975668412(6.390323e-04) ; R600-NEXT: 209715200(1.972152e-31), 0(0.000000e+00) -; R600-NEXT: MUL_IEEE T3.X, T1.X, literal.x, -; R600-NEXT: MUL_IEEE T2.Y, PS, literal.y, +; R600-NEXT: MUL_IEEE T3.X, PS, literal.x, +; R600-NEXT: MUL_IEEE T2.Y, T1.X, literal.y, ; R600-NEXT: MULADD_IEEE T4.Z, T0.Y, literal.z, PV.W, ; R600-NEXT: FLT_TO_INT T0.W, PV.Z, ; R600-NEXT: MIN_INT * T2.W, PV.Y, literal.w, -; R600-NEXT: 2130706432(1.701412e+38), 209715200(1.972152e-31) +; R600-NEXT: 209715200(1.972152e-31), 2130706432(1.701412e+38) ; R600-NEXT: 1079283712(3.321289e+00), 381(5.338947e-43) ; R600-NEXT: ADD_INT T4.X, PS, literal.x, ; R600-NEXT: MAX_INT T0.Y, PV.W, literal.y, @@ -1325,7 +1320,7 @@ define amdgpu_kernel void @s_exp10_v3f32(ptr addrspace(1) %out, <3 x float> %in) ; R600-NEXT: 102(1.429324e-43), -229(nan) ; R600-NEXT: ADD_INT * T6.X, T0.W, literal.x, ; R600-NEXT: -127(nan), 0(0.000000e+00) -; R600-NEXT: ALU clause starting at 107: +; R600-NEXT: ALU clause starting at 106: ; R600-NEXT: SETGT_UINT T0.Y, T0.W, literal.x, ; R600-NEXT: CNDE_INT T0.Z, T3.W, T0.Z, T2.W, BS:VEC_102/SCL_221 ; R600-NEXT: SETGT_INT T2.W, T0.W, literal.y, @@ -1341,25 +1336,25 @@ define amdgpu_kernel void @s_exp10_v3f32(ptr addrspace(1) %out, <3 x float> %in) ; R600-NEXT: SETGT_UINT T5.X, T1.Y, literal.x, ; R600-NEXT: CNDE_INT T4.Y, PS, PV.Z, PV.W, ; R600-NEXT: MAX_INT T0.Z, T1.Y, literal.y, -; R600-NEXT: MUL_IEEE T4.W, T1.Z, literal.z, -; R600-NEXT: MUL_IEEE * T5.W, PV.Y, literal.w, +; R600-NEXT: MUL_IEEE T4.W, PV.Y, literal.z, +; R600-NEXT: MUL_IEEE * T5.W, T1.Z, literal.w, ; R600-NEXT: 254(3.559298e-43), -330(nan) -; R600-NEXT: 2130706432(1.701412e+38), 209715200(1.972152e-31) -; R600-NEXT: CNDE_INT T6.X, T3.W, PS, T3.Y, BS:VEC_021/SCL_122 -; R600-NEXT: MUL_IEEE T3.Y, PV.W, literal.x, +; R600-NEXT: 209715200(1.972152e-31), 2130706432(1.701412e+38) +; R600-NEXT: MUL_IEEE T6.X, PS, literal.x, +; R600-NEXT: CNDE_INT T3.Y, T3.W, PV.W, T3.Y, BS:VEC_021/SCL_122 ; R600-NEXT: ADD_INT T0.Z, PV.Z, literal.y, ; R600-NEXT: ADD_INT T3.W, T1.Y, literal.z, -; R600-NEXT: SETGT_UINT * T5.W, T1.Y, literal.w, +; R600-NEXT: SETGT_UINT * T4.W, T1.Y, literal.w, ; R600-NEXT: 2130706432(1.701412e+38), 204(2.858649e-43) ; R600-NEXT: 102(1.429324e-43), -229(nan) ; R600-NEXT: CNDE_INT T8.X, PS, PV.Z, PV.W, ; R600-NEXT: SETGT_INT T5.Y, T1.Y, literal.x, -; R600-NEXT: CNDE_INT T0.Z, T0.Y, T4.W, PV.Y, BS:VEC_120/SCL_212 -; R600-NEXT: CNDE_INT T2.W, T2.W, PV.X, T1.Z, +; R600-NEXT: CNDE_INT T0.Z, T2.W, PV.Y, T1.Z, +; R600-NEXT: CNDE_INT T2.W, T0.Y, T5.W, PV.X, BS:VEC_120/SCL_212 ; R600-NEXT: LSHL * T3.W, T4.Y, literal.y, ; R600-NEXT: -127(nan), 23(3.222986e-44) ; R600-NEXT: ADD_INT T6.X, PS, literal.x, -; R600-NEXT: CNDE_INT T0.Y, T0.W, PV.W, PV.Z, +; R600-NEXT: CNDE_INT T0.Y, T0.W, PV.Z, PV.W, ; R600-NEXT: CNDE_INT T0.Z, PV.Y, PV.X, T1.Y, ; R600-NEXT: CNDE_INT T0.W, T5.X, T7.X, T4.X, ; R600-NEXT: SETGT_INT * T2.W, T1.Y, literal.y, @@ -1367,18 +1362,18 @@ define amdgpu_kernel void @s_exp10_v3f32(ptr addrspace(1) %out, <3 x float> %in) ; R600-NEXT: CNDE_INT T4.X, PS, PV.Z, PV.W, ; R600-NEXT: MUL_IEEE T0.Y, PV.Y, PV.X, ; R600-NEXT: SETGT T0.Z, literal.x, KC0[3].Z, -; R600-NEXT: CNDE_INT T0.W, T5.W, T2.Y, T1.W, -; R600-NEXT: MUL_IEEE * T1.W, T3.X, literal.y, +; R600-NEXT: MUL_IEEE T0.W, T2.Y, literal.y, +; R600-NEXT: CNDE_INT * T1.W, T4.W, T3.X, T1.W, ; R600-NEXT: -1036817932(-4.485347e+01), 2130706432(1.701412e+38) -; R600-NEXT: CNDE_INT T3.X, T5.X, T3.X, PS, -; R600-NEXT: CNDE_INT T1.Y, T5.Y, PV.W, T1.X, +; R600-NEXT: CNDE_INT T1.X, T5.Y, PS, T1.X, +; R600-NEXT: CNDE_INT T1.Y, T5.X, T2.Y, PV.W, ; R600-NEXT: CNDE T0.Z, PV.Z, PV.Y, 0.0, ; R600-NEXT: SETGT T0.W, KC0[3].Z, literal.x, ; R600-NEXT: LSHL * T1.W, PV.X, literal.y, ; R600-NEXT: 1109008539(3.853184e+01), 23(3.222986e-44) -; R600-NEXT: ADD_INT T1.X, PS, literal.x, +; R600-NEXT: ADD_INT T3.X, PS, literal.x, ; R600-NEXT: CNDE T0.Y, PV.W, PV.Z, literal.y, -; R600-NEXT: CNDE_INT T0.Z, T2.W, PV.Y, PV.X, +; R600-NEXT: CNDE_INT T0.Z, T2.W, PV.X, PV.Y, ; R600-NEXT: CNDE T0.W, T2.X, T0.X, 0.0, ; R600-NEXT: SETGT * T1.W, KC0[3].Y, literal.z, ; R600-NEXT: 1065353216(1.000000e+00), 2139095040(INF) @@ -1399,197 +1394,193 @@ define amdgpu_kernel void @s_exp10_v3f32(ptr addrspace(1) %out, <3 x float> %in) ; ; CM-LABEL: s_exp10_v3f32: ; CM: ; %bb.0: -; CM-NEXT: ALU 102, @6, KC0[CB0:0-32], KC1[] -; CM-NEXT: ALU 80, @109, KC0[CB0:0-32], KC1[] -; CM-NEXT: MEM_RAT_CACHELESS STORE_DWORD T1, T3.X -; CM-NEXT: MEM_RAT_CACHELESS STORE_DWORD T2.X, T0.X +; CM-NEXT: ALU 101, @6, KC0[CB0:0-32], KC1[] +; CM-NEXT: ALU 77, @108, KC0[CB0:0-32], KC1[] +; CM-NEXT: MEM_RAT_CACHELESS STORE_DWORD T0, T1.X +; CM-NEXT: MEM_RAT_CACHELESS STORE_DWORD T2.X, T3.X ; CM-NEXT: CF_END ; CM-NEXT: PAD ; CM-NEXT: ALU clause starting at 6: ; CM-NEXT: AND_INT * T0.W, KC0[3].Y, literal.x, ; CM-NEXT: -4096(nan), 0(0.000000e+00) -; CM-NEXT: MUL_IEEE T0.Z, PV.W, literal.x, ; CM-NEXT: ADD * T1.W, KC0[3].Y, -PV.W, -; CM-NEXT: 1079283712(3.321289e+00), 0(0.000000e+00) -; CM-NEXT: MUL_IEEE T1.Z, PV.W, literal.x, -; CM-NEXT: RNDNE * T2.W, PV.Z, -; CM-NEXT: 975668412(6.390323e-04), 0(0.000000e+00) -; CM-NEXT: TRUNC T2.Z, PV.W, +; CM-NEXT: MUL_IEEE T0.Z, PV.W, literal.x, +; CM-NEXT: MUL_IEEE * T2.W, T0.W, literal.y, +; CM-NEXT: 975668412(6.390323e-04), 1079283712(3.321289e+00) +; CM-NEXT: RNDNE T1.Z, PV.W, ; CM-NEXT: MULADD_IEEE * T1.W, T1.W, literal.x, PV.Z, ; CM-NEXT: 1079283712(3.321289e+00), 0(0.000000e+00) -; CM-NEXT: MULADD_IEEE T0.Y, T0.W, literal.x, PV.W, -; CM-NEXT: ADD T0.Z, T0.Z, -T2.W, -; CM-NEXT: FLT_TO_INT * T0.W, PV.Z, +; CM-NEXT: MULADD_IEEE T0.Z, T0.W, literal.x, PV.W, +; CM-NEXT: ADD * T0.W, T2.W, -PV.Z, BS:VEC_120/SCL_212 ; CM-NEXT: 975668412(6.390323e-04), 0(0.000000e+00) -; CM-NEXT: MIN_INT T1.Z, PV.W, literal.x, -; CM-NEXT: ADD * T1.W, PV.Z, PV.Y, +; CM-NEXT: TRUNC T1.Z, T1.Z, +; CM-NEXT: ADD * T0.W, PV.W, PV.Z, +; CM-NEXT: EXP_IEEE T0.X, T0.W, +; CM-NEXT: EXP_IEEE T0.Y (MASKED), T0.W, +; CM-NEXT: EXP_IEEE T0.Z (MASKED), T0.W, +; CM-NEXT: EXP_IEEE * T0.W (MASKED), T0.W, +; CM-NEXT: FLT_TO_INT T0.Z, T1.Z, +; CM-NEXT: MUL_IEEE * T0.W, PV.X, literal.x, +; CM-NEXT: 209715200(1.972152e-31), 0(0.000000e+00) +; CM-NEXT: MUL_IEEE T0.Y, PV.W, literal.x, +; CM-NEXT: MAX_INT T1.Z, PV.Z, literal.y, +; CM-NEXT: MIN_INT * T1.W, PV.Z, literal.z, +; CM-NEXT: 209715200(1.972152e-31), -330(nan) ; CM-NEXT: 381(5.338947e-43), 0(0.000000e+00) -; CM-NEXT: EXP_IEEE T0.X, T1.W, -; CM-NEXT: EXP_IEEE T0.Y (MASKED), T1.W, -; CM-NEXT: EXP_IEEE T0.Z (MASKED), T1.W, -; CM-NEXT: EXP_IEEE * T0.W (MASKED), T1.W, -; CM-NEXT: MUL_IEEE T0.Y, PV.X, literal.x, -; CM-NEXT: ADD_INT T0.Z, T1.Z, literal.y, -; CM-NEXT: MAX_INT * T1.W, T0.W, literal.z, -; CM-NEXT: 2130706432(1.701412e+38), -254(nan) -; CM-NEXT: -330(nan), 0(0.000000e+00) -; CM-NEXT: ADD_INT T1.X, T0.W, literal.x, -; CM-NEXT: ADD_INT T1.Y, PV.W, literal.y, -; CM-NEXT: ADD_INT T1.Z, T0.W, literal.z, -; CM-NEXT: SETGT_UINT * T1.W, T0.W, literal.w, -; CM-NEXT: -127(nan), 204(2.858649e-43) +; CM-NEXT: ADD_INT T1.X, PV.W, literal.x, +; CM-NEXT: ADD_INT T1.Y, PV.Z, literal.y, +; CM-NEXT: ADD_INT T1.Z, T0.Z, literal.z, +; CM-NEXT: SETGT_UINT * T1.W, T0.Z, literal.w, +; CM-NEXT: -254(nan), 204(2.858649e-43) ; CM-NEXT: 102(1.429324e-43), -229(nan) -; CM-NEXT: SETGT_UINT T2.X, T0.W, literal.x, -; CM-NEXT: CNDE_INT T1.Y, PV.W, PV.Y, PV.Z, -; CM-NEXT: SETGT_INT T1.Z, T0.W, literal.y, -; CM-NEXT: MUL_IEEE * T2.W, T0.X, literal.z, -; CM-NEXT: 254(3.559298e-43), -127(nan) -; CM-NEXT: 209715200(1.972152e-31), 0(0.000000e+00) -; CM-NEXT: MUL_IEEE T3.X, PV.W, literal.x, -; CM-NEXT: CNDE_INT T1.Y, PV.Z, PV.Y, T0.W, -; CM-NEXT: CNDE_INT T0.Z, PV.X, T1.X, T0.Z, -; CM-NEXT: SETGT_INT * T0.W, T0.W, literal.y, -; CM-NEXT: 209715200(1.972152e-31), 127(1.779649e-43) +; CM-NEXT: ADD_INT T2.X, T0.Z, literal.x, +; CM-NEXT: SETGT_UINT T2.Y, T0.Z, literal.y, +; CM-NEXT: CNDE_INT T1.Z, PV.W, PV.Y, PV.Z, +; CM-NEXT: SETGT_INT * T2.W, T0.Z, literal.x, +; CM-NEXT: -127(nan), 254(3.559298e-43) +; CM-NEXT: MUL_IEEE T3.X, T0.X, literal.x, +; CM-NEXT: CNDE_INT T1.Y, PV.W, PV.Z, T0.Z, +; CM-NEXT: CNDE_INT T1.Z, PV.Y, PV.X, T1.X, +; CM-NEXT: SETGT_INT * T3.W, T0.Z, literal.y, +; CM-NEXT: 2130706432(1.701412e+38), 127(1.779649e-43) ; CM-NEXT: CNDE_INT T1.Y, PV.W, PV.Y, PV.Z, -; CM-NEXT: CNDE_INT T0.Z, T1.W, PV.X, T2.W, -; CM-NEXT: MUL_IEEE * T1.W, T0.Y, literal.x, +; CM-NEXT: MUL_IEEE T0.Z, PV.X, literal.x, +; CM-NEXT: CNDE_INT * T0.W, T1.W, T0.Y, T0.W, ; CM-NEXT: 2130706432(1.701412e+38), 0(0.000000e+00) -; CM-NEXT: CNDE_INT T1.X, T2.X, T0.Y, PV.W, -; CM-NEXT: CNDE_INT T0.Y, T1.Z, PV.Z, T0.X, +; CM-NEXT: CNDE_INT T0.X, T2.W, PV.W, T0.X, +; CM-NEXT: CNDE_INT T0.Y, T2.Y, T3.X, PV.Z, ; CM-NEXT: LSHL T0.Z, PV.Y, literal.x, -; CM-NEXT: AND_INT * T1.W, KC0[3].Z, literal.y, +; CM-NEXT: AND_INT * T0.W, KC0[3].Z, literal.y, ; CM-NEXT: 23(3.222986e-44), -4096(nan) -; CM-NEXT: MUL_IEEE T0.X, PV.W, literal.x, ; CM-NEXT: ADD T1.Y, KC0[3].Z, -PV.W, -; CM-NEXT: ADD_INT T0.Z, PV.Z, literal.y, -; CM-NEXT: CNDE_INT * T0.W, T0.W, PV.Y, PV.X, -; CM-NEXT: 1079283712(3.321289e+00), 1065353216(1.000000e+00) -; CM-NEXT: MUL_IEEE T0.Y, PV.W, PV.Z, -; CM-NEXT: MUL_IEEE T0.Z, PV.Y, literal.x, -; CM-NEXT: RNDNE * T0.W, PV.X, -; CM-NEXT: 975668412(6.390323e-04), 0(0.000000e+00) +; CM-NEXT: ADD_INT T0.Z, PV.Z, literal.x, +; CM-NEXT: CNDE_INT * T1.W, T3.W, PV.X, PV.Y, +; CM-NEXT: 1065353216(1.000000e+00), 0(0.000000e+00) +; CM-NEXT: MUL_IEEE T0.X, PV.W, PV.Z, +; CM-NEXT: MUL_IEEE T0.Y, PV.Y, literal.x, +; CM-NEXT: MUL_IEEE T0.Z, T0.W, literal.y, +; CM-NEXT: AND_INT * T1.W, KC0[3].W, literal.z, +; CM-NEXT: 975668412(6.390323e-04), 1079283712(3.321289e+00) +; CM-NEXT: -4096(nan), 0(0.000000e+00) ; CM-NEXT: SETGT T1.X, literal.x, KC0[3].Y, -; CM-NEXT: TRUNC T2.Y, PV.W, -; CM-NEXT: AND_INT T1.Z, KC0[3].W, literal.y, -; CM-NEXT: MULADD_IEEE * T2.W, T1.Y, literal.z, PV.Z, -; CM-NEXT: -1036817932(-4.485347e+01), -4096(nan) -; CM-NEXT: 1079283712(3.321289e+00), 0(0.000000e+00) -; CM-NEXT: MULADD_IEEE T2.X, T1.W, literal.x, PV.W, -; CM-NEXT: MUL_IEEE T1.Y, PV.Z, literal.y, -; CM-NEXT: FLT_TO_INT T0.Z, PV.Y, -; CM-NEXT: ADD * T1.W, KC0[3].W, -PV.Z, +; CM-NEXT: ADD T2.Y, KC0[3].W, -PV.W, +; CM-NEXT: RNDNE T1.Z, PV.Z, +; CM-NEXT: MULADD_IEEE * T2.W, T1.Y, literal.y, PV.Y, +; CM-NEXT: -1036817932(-4.485347e+01), 1079283712(3.321289e+00) +; CM-NEXT: MULADD_IEEE T2.X, T0.W, literal.x, PV.W, +; CM-NEXT: ADD T0.Y, T0.Z, -PV.Z, +; CM-NEXT: MUL_IEEE T0.Z, PV.Y, literal.x, +; CM-NEXT: MUL_IEEE * T0.W, T1.W, literal.y, BS:VEC_120/SCL_212 ; CM-NEXT: 975668412(6.390323e-04), 1079283712(3.321289e+00) -; CM-NEXT: ADD T0.X, T0.X, -T0.W, -; CM-NEXT: MUL_IEEE T2.Y, PV.W, literal.x, -; CM-NEXT: MAX_INT T2.Z, PV.Z, literal.y, -; CM-NEXT: RNDNE * T0.W, PV.Y, -; CM-NEXT: 975668412(6.390323e-04), -330(nan) -; CM-NEXT: TRUNC T3.X, PV.W, -; CM-NEXT: ADD_INT T3.Y, PV.Z, literal.x, -; CM-NEXT: MULADD_IEEE T2.Z, T1.W, literal.y, PV.Y, -; CM-NEXT: ADD * T1.W, PV.X, T2.X, -; CM-NEXT: 204(2.858649e-43), 1079283712(3.321289e+00) -; CM-NEXT: EXP_IEEE T0.X, T1.W, -; CM-NEXT: EXP_IEEE T0.Y (MASKED), T1.W, -; CM-NEXT: EXP_IEEE T0.Z (MASKED), T1.W, -; CM-NEXT: EXP_IEEE * T0.W (MASKED), T1.W, -; CM-NEXT: ADD_INT T2.X, T0.Z, literal.x, -; CM-NEXT: MULADD_IEEE T2.Y, T1.Z, literal.y, T2.Z, BS:VEC_102/SCL_221 -; CM-NEXT: ADD T1.Z, T1.Y, -T0.W, -; CM-NEXT: MUL_IEEE * T0.W, PV.X, literal.z, -; CM-NEXT: 102(1.429324e-43), 975668412(6.390323e-04) -; CM-NEXT: 2130706432(1.701412e+38), 0(0.000000e+00) -; CM-NEXT: SETGT_UINT T4.X, T0.Z, literal.x, -; CM-NEXT: MUL_IEEE T1.Y, PV.W, literal.y, -; CM-NEXT: SETGT_UINT T2.Z, T0.Z, literal.z, -; CM-NEXT: ADD * T1.W, PV.Z, PV.Y, -; CM-NEXT: -229(nan), 2130706432(1.701412e+38) -; CM-NEXT: 254(3.559298e-43), 0(0.000000e+00) +; CM-NEXT: TRUNC T3.X, T1.Z, +; CM-NEXT: RNDNE T1.Y, PV.W, +; CM-NEXT: MULADD_IEEE T0.Z, T2.Y, literal.x, PV.Z, +; CM-NEXT: ADD * T2.W, PV.Y, PV.X, +; CM-NEXT: 1079283712(3.321289e+00), 0(0.000000e+00) +; CM-NEXT: EXP_IEEE T0.X (MASKED), T2.W, +; CM-NEXT: EXP_IEEE T0.Y, T2.W, +; CM-NEXT: EXP_IEEE T0.Z (MASKED), T2.W, +; CM-NEXT: EXP_IEEE * T0.W (MASKED), T2.W, +; CM-NEXT: MULADD_IEEE T2.X, T1.W, literal.x, T0.Z, +; CM-NEXT: ADD T2.Y, T0.W, -T1.Y, BS:VEC_120/SCL_212 +; CM-NEXT: FLT_TO_INT T0.Z, T3.X, +; CM-NEXT: MUL_IEEE * T0.W, PV.Y, literal.y, +; CM-NEXT: 975668412(6.390323e-04), 209715200(1.972152e-31) +; CM-NEXT: MUL_IEEE T3.X, PV.W, literal.x, +; CM-NEXT: SETGT_UINT T3.Y, PV.Z, literal.y, +; CM-NEXT: TRUNC T1.Z, T1.Y, +; CM-NEXT: ADD * T1.W, PV.Y, PV.X, +; CM-NEXT: 209715200(1.972152e-31), -229(nan) ; CM-NEXT: EXP_IEEE T1.X (MASKED), T1.W, -; CM-NEXT: EXP_IEEE T1.Y (MASKED), T1.W, -; CM-NEXT: EXP_IEEE T1.Z, T1.W, +; CM-NEXT: EXP_IEEE T1.Y, T1.W, +; CM-NEXT: EXP_IEEE T1.Z (MASKED), T1.W, ; CM-NEXT: EXP_IEEE * T1.W (MASKED), T1.W, -; CM-NEXT: ALU clause starting at 109: -; CM-NEXT: CNDE_INT T5.X, T2.Z, T0.W, T1.Y, -; CM-NEXT: CNDE_INT T1.Y, T4.X, T3.Y, T2.X, -; CM-NEXT: FLT_TO_INT T3.Z, T3.X, BS:VEC_120/SCL_212 -; CM-NEXT: MUL_IEEE * T0.W, T1.Z, literal.x, BS:VEC_120/SCL_212 -; CM-NEXT: 2130706432(1.701412e+38), 0(0.000000e+00) -; CM-NEXT: SETGT_INT T2.X, T0.Z, literal.x, -; CM-NEXT: MUL_IEEE T2.Y, T0.X, literal.y, -; CM-NEXT: MUL_IEEE T4.Z, PV.W, literal.z, -; CM-NEXT: SETGT_UINT * T1.W, PV.Z, literal.w, -; CM-NEXT: -127(nan), 209715200(1.972152e-31) -; CM-NEXT: 2130706432(1.701412e+38), 254(3.559298e-43) -; CM-NEXT: CNDE_INT T3.X, PV.W, T0.W, PV.Z, -; CM-NEXT: MUL_IEEE T3.Y, PV.Y, literal.x, -; CM-NEXT: CNDE_INT T4.Z, PV.X, T1.Y, T0.Z, -; CM-NEXT: MAX_INT * T0.W, T3.Z, literal.y, -; CM-NEXT: 209715200(1.972152e-31), -330(nan) -; CM-NEXT: ADD_INT T6.X, PV.W, literal.x, -; CM-NEXT: ADD_INT T1.Y, T3.Z, literal.y, -; CM-NEXT: SETGT_UINT T5.Z, T3.Z, literal.z, -; CM-NEXT: MUL_IEEE * T0.W, T1.Z, literal.w, BS:VEC_120/SCL_212 +; CM-NEXT: FLT_TO_INT T2.X, T1.Z, +; CM-NEXT: MUL_IEEE T2.Y, PV.Y, literal.x, +; CM-NEXT: CNDE_INT T1.Z, T3.Y, T3.X, T0.W, +; CM-NEXT: SETGT_INT * T0.W, T0.Z, literal.y, BS:VEC_120/SCL_212 +; CM-NEXT: 209715200(1.972152e-31), -127(nan) +; CM-NEXT: CNDE_INT T3.X, PV.W, PV.Z, T0.Y, +; CM-NEXT: MUL_IEEE * T4.Y, PV.Y, literal.x, +; CM-NEXT: 209715200(1.972152e-31), 0(0.000000e+00) +; CM-NEXT: ALU clause starting at 108: +; CM-NEXT: SETGT_UINT T1.Z, T2.X, literal.x, +; CM-NEXT: MAX_INT * T1.W, T0.Z, literal.y, +; CM-NEXT: -229(nan), -330(nan) +; CM-NEXT: ADD_INT T4.X, PV.W, literal.x, +; CM-NEXT: ADD_INT T5.Y, T0.Z, literal.y, +; CM-NEXT: CNDE_INT T2.Z, PV.Z, T4.Y, T2.Y, +; CM-NEXT: SETGT_INT * T1.W, T2.X, literal.z, ; CM-NEXT: 204(2.858649e-43), 102(1.429324e-43) -; CM-NEXT: -229(nan), 209715200(1.972152e-31) -; CM-NEXT: MUL_IEEE T7.X, PV.W, literal.x, -; CM-NEXT: MIN_INT T4.Y, T3.Z, literal.y, -; CM-NEXT: CNDE_INT T6.Z, PV.Z, PV.X, PV.Y, -; CM-NEXT: SETGT_INT * T2.W, T3.Z, literal.z, -; CM-NEXT: 209715200(1.972152e-31), 381(5.338947e-43) ; CM-NEXT: -127(nan), 0(0.000000e+00) -; CM-NEXT: CNDE_INT T6.X, PV.W, PV.Z, T3.Z, -; CM-NEXT: MIN_INT T1.Y, T0.Z, literal.x, -; CM-NEXT: ADD_INT T6.Z, PV.Y, literal.y, -; CM-NEXT: ADD_INT * T3.W, T3.Z, literal.z, BS:VEC_120/SCL_212 -; CM-NEXT: 381(5.338947e-43), -254(nan) -; CM-NEXT: -127(nan), 0(0.000000e+00) -; CM-NEXT: CNDE_INT T8.X, T1.W, PV.W, PV.Z, -; CM-NEXT: SETGT_INT T4.Y, T3.Z, literal.x, -; CM-NEXT: ADD_INT T3.Z, PV.Y, literal.y, -; CM-NEXT: ADD_INT * T1.W, T0.Z, literal.z, BS:VEC_120/SCL_212 +; CM-NEXT: CNDE_INT T5.X, PV.W, PV.Z, T1.Y, +; CM-NEXT: MUL_IEEE T0.Y, T0.Y, literal.x, +; CM-NEXT: MAX_INT T2.Z, T2.X, literal.y, +; CM-NEXT: CNDE_INT * T2.W, T3.Y, PV.X, PV.Y, BS:VEC_120/SCL_212 +; CM-NEXT: 2130706432(1.701412e+38), -330(nan) +; CM-NEXT: CNDE_INT T4.X, T0.W, PV.W, T0.Z, +; CM-NEXT: ADD_INT T2.Y, PV.Z, literal.x, +; CM-NEXT: ADD_INT T2.Z, T2.X, literal.y, +; CM-NEXT: MIN_INT * T0.W, T2.X, literal.z, +; CM-NEXT: 204(2.858649e-43), 102(1.429324e-43) +; CM-NEXT: 381(5.338947e-43), 0(0.000000e+00) +; CM-NEXT: ADD_INT T6.X, PV.W, literal.x, +; CM-NEXT: ADD_INT T3.Y, T2.X, literal.y, +; CM-NEXT: SETGT_UINT T3.Z, T2.X, literal.z, +; CM-NEXT: CNDE_INT * T0.W, T1.Z, PV.Y, PV.Z, +; CM-NEXT: -254(nan), -127(nan) +; CM-NEXT: 254(3.559298e-43), 0(0.000000e+00) +; CM-NEXT: MUL_IEEE T7.X, T1.Y, literal.x, +; CM-NEXT: CNDE_INT T1.Y, T1.W, PV.W, T2.X, +; CM-NEXT: CNDE_INT T1.Z, PV.Z, PV.Y, PV.X, +; CM-NEXT: MIN_INT * T0.W, T0.Z, literal.y, +; CM-NEXT: 2130706432(1.701412e+38), 381(5.338947e-43) +; CM-NEXT: SETGT_INT T2.X, T2.X, literal.x, +; CM-NEXT: ADD_INT T2.Y, PV.W, literal.y, +; CM-NEXT: ADD_INT T2.Z, T0.Z, literal.z, +; CM-NEXT: SETGT_UINT * T0.W, T0.Z, literal.w, ; CM-NEXT: 127(1.779649e-43), -254(nan) -; CM-NEXT: -127(nan), 0(0.000000e+00) -; CM-NEXT: CNDE_INT T9.X, T2.Z, PV.W, PV.Z, -; CM-NEXT: SETGT_INT T1.Y, T0.Z, literal.x, BS:VEC_120/SCL_212 -; CM-NEXT: CNDE_INT T0.Z, PV.Y, T6.X, PV.X, -; CM-NEXT: CNDE_INT * T0.W, T5.Z, T7.X, T0.W, BS:VEC_201 -; CM-NEXT: 127(1.779649e-43), 0(0.000000e+00) -; CM-NEXT: CNDE_INT T6.X, T2.W, PV.W, T1.Z, -; CM-NEXT: LSHL T5.Y, PV.Z, literal.x, -; CM-NEXT: CNDE_INT T0.Z, PV.Y, T4.Z, PV.X, -; CM-NEXT: CNDE_INT * T0.W, T4.X, T3.Y, T2.Y, -; CM-NEXT: 23(3.222986e-44), 0(0.000000e+00) -; CM-NEXT: CNDE_INT T0.X, T2.X, PV.W, T0.X, -; CM-NEXT: LSHL T2.Y, PV.Z, literal.x, +; CM-NEXT: -127(nan), 254(3.559298e-43) +; CM-NEXT: CNDE_INT T6.X, PV.W, PV.Z, PV.Y, +; CM-NEXT: SETGT_INT T2.Y, T0.Z, literal.x, +; CM-NEXT: CNDE_INT T0.Z, PV.X, T1.Y, T1.Z, +; CM-NEXT: MUL_IEEE * T1.W, T7.X, literal.y, +; CM-NEXT: 127(1.779649e-43), 2130706432(1.701412e+38) +; CM-NEXT: CNDE_INT T7.X, T3.Z, T7.X, PV.W, +; CM-NEXT: LSHL T1.Y, PV.Z, literal.x, +; CM-NEXT: CNDE_INT T0.Z, PV.Y, T4.X, PV.X, BS:VEC_021/SCL_122 +; CM-NEXT: MUL_IEEE * T1.W, T0.Y, literal.y, +; CM-NEXT: 23(3.222986e-44), 2130706432(1.701412e+38) +; CM-NEXT: CNDE_INT T4.X, T0.W, T0.Y, PV.W, +; CM-NEXT: LSHL T0.Y, PV.Z, literal.x, ; CM-NEXT: ADD_INT T0.Z, PV.Y, literal.y, -; CM-NEXT: CNDE_INT * T0.W, T4.Y, PV.X, T3.X, BS:VEC_021/SCL_122 +; CM-NEXT: CNDE_INT * T0.W, T2.X, T5.X, PV.X, ; CM-NEXT: 23(3.222986e-44), 1065353216(1.000000e+00) ; CM-NEXT: MUL_IEEE T2.X, PV.W, PV.Z, -; CM-NEXT: SETGT T3.Y, literal.x, KC0[3].W, +; CM-NEXT: SETGT T1.Y, literal.x, KC0[3].W, ; CM-NEXT: ADD_INT T0.Z, PV.Y, literal.y, -; CM-NEXT: CNDE_INT * T0.W, T1.Y, PV.X, T5.X, +; CM-NEXT: CNDE_INT * T0.W, T2.Y, T3.X, PV.X, ; CM-NEXT: -1036817932(-4.485347e+01), 1065353216(1.000000e+00) -; CM-NEXT: MUL_IEEE T0.X, PV.W, PV.Z, -; CM-NEXT: SETGT T1.Y, literal.x, KC0[3].Z, +; CM-NEXT: MUL_IEEE T3.X, PV.W, PV.Z, +; CM-NEXT: SETGT T0.Y, literal.x, KC0[3].Z, ; CM-NEXT: CNDE T0.Z, PV.Y, PV.X, 0.0, ; CM-NEXT: SETGT * T0.W, KC0[3].W, literal.y, ; CM-NEXT: -1036817932(-4.485347e+01), 1109008539(3.853184e+01) ; CM-NEXT: CNDE T2.X, PV.W, PV.Z, literal.x, -; CM-NEXT: CNDE T1.Y, PV.Y, PV.X, 0.0, +; CM-NEXT: CNDE T0.Y, PV.Y, PV.X, 0.0, ; CM-NEXT: SETGT T0.Z, KC0[3].Z, literal.y, ; CM-NEXT: ADD_INT * T0.W, KC0[2].Y, literal.z, ; CM-NEXT: 2139095040(INF), 1109008539(3.853184e+01) ; CM-NEXT: 8(1.121039e-44), 0(0.000000e+00) -; CM-NEXT: LSHR T0.X, PV.W, literal.x, -; CM-NEXT: CNDE T1.Y, PV.Z, PV.Y, literal.y, -; CM-NEXT: CNDE T0.Z, T1.X, T0.Y, 0.0, +; CM-NEXT: LSHR T3.X, PV.W, literal.x, +; CM-NEXT: CNDE T0.Y, PV.Z, PV.Y, literal.y, +; CM-NEXT: CNDE T0.Z, T1.X, T0.X, 0.0, ; CM-NEXT: SETGT * T0.W, KC0[3].Y, literal.z, ; CM-NEXT: 2(2.802597e-45), 2139095040(INF) ; CM-NEXT: 1109008539(3.853184e+01), 0(0.000000e+00) -; CM-NEXT: CNDE * T1.X, PV.W, PV.Z, literal.x, +; CM-NEXT: CNDE * T0.X, PV.W, PV.Z, literal.x, ; CM-NEXT: 2139095040(INF), 0(0.000000e+00) -; CM-NEXT: LSHR * T3.X, KC0[2].Y, literal.x, +; CM-NEXT: LSHR * T1.X, KC0[2].Y, literal.x, ; CM-NEXT: 2(2.802597e-45), 0(0.000000e+00) %result = call <3 x float> @llvm.exp10.v3f32(<3 x float> %in) store <3 x float> %result, ptr addrspace(1) %out @@ -2052,227 +2043,224 @@ define amdgpu_kernel void @s_exp10_v4f32(ptr addrspace(1) %out, <4 x float> %in) ; R600-LABEL: s_exp10_v4f32: ; R600: ; %bb.0: ; R600-NEXT: ALU 98, @6, KC0[CB0:0-32], KC1[] -; R600-NEXT: ALU 98, @105, KC0[CB0:0-32], KC1[] -; R600-NEXT: ALU 24, @204, KC0[CB0:0-32], KC1[] +; R600-NEXT: ALU 95, @105, KC0[CB0:0-32], KC1[] +; R600-NEXT: ALU 24, @201, KC0[CB0:0-32], KC1[] ; R600-NEXT: MEM_RAT_CACHELESS STORE_RAW T1.XYZW, T0.X, 1 ; R600-NEXT: CF_END ; R600-NEXT: PAD ; R600-NEXT: ALU clause starting at 6: ; R600-NEXT: AND_INT * T0.W, KC0[3].Z, literal.x, ; R600-NEXT: -4096(nan), 0(0.000000e+00) -; R600-NEXT: ADD T1.W, KC0[3].Z, -PV.W, -; R600-NEXT: MUL_IEEE * T2.W, PV.W, literal.x, +; R600-NEXT: ADD * T1.W, KC0[3].Z, -PV.W, +; R600-NEXT: MUL_IEEE T2.W, PV.W, literal.x, +; R600-NEXT: MUL_IEEE * T3.W, T0.W, literal.y, +; R600-NEXT: 975668412(6.390323e-04), 1079283712(3.321289e+00) +; R600-NEXT: RNDNE T4.W, PS, +; R600-NEXT: MULADD_IEEE * T1.W, T1.W, literal.x, PV.W, BS:VEC_021/SCL_122 ; R600-NEXT: 1079283712(3.321289e+00), 0(0.000000e+00) -; R600-NEXT: RNDNE T3.W, PS, -; R600-NEXT: MUL_IEEE * T4.W, PV.W, literal.x, +; R600-NEXT: MULADD_IEEE T0.W, T0.W, literal.x, PS, +; R600-NEXT: ADD * T1.W, T3.W, -PV.W, ; R600-NEXT: 975668412(6.390323e-04), 0(0.000000e+00) -; R600-NEXT: MULADD_IEEE T1.W, T1.W, literal.x, PS, -; R600-NEXT: TRUNC * T4.W, PV.W, -; R600-NEXT: 1079283712(3.321289e+00), 0(0.000000e+00) -; R600-NEXT: FLT_TO_INT T0.Z, PS, -; R600-NEXT: MULADD_IEEE T0.W, T0.W, literal.x, PV.W, -; R600-NEXT: ADD * T1.W, T2.W, -T3.W, -; R600-NEXT: 975668412(6.390323e-04), 0(0.000000e+00) -; R600-NEXT: ADD T1.Z, PS, PV.W, -; R600-NEXT: MAX_INT T0.W, PV.Z, literal.x, -; R600-NEXT: MIN_INT * T1.W, PV.Z, literal.y, -; R600-NEXT: -330(nan), 381(5.338947e-43) -; R600-NEXT: ADD_INT T0.X, PS, literal.x, -; R600-NEXT: ADD_INT T0.Y, PV.W, literal.y, -; R600-NEXT: ADD_INT T2.Z, T0.Z, literal.z, -; R600-NEXT: SETGT_UINT T0.W, T0.Z, literal.w, -; R600-NEXT: EXP_IEEE * T1.X, PV.Z, -; R600-NEXT: -254(nan), 204(2.858649e-43) -; R600-NEXT: 102(1.429324e-43), -229(nan) -; R600-NEXT: ADD_INT T2.X, T0.Z, literal.x, -; R600-NEXT: SETGT_UINT T1.Y, T0.Z, literal.y, -; R600-NEXT: CNDE_INT T1.Z, PV.W, PV.Y, PV.Z, -; R600-NEXT: SETGT_INT T1.W, T0.Z, literal.x, -; R600-NEXT: MUL_IEEE * T2.W, PS, literal.z, -; R600-NEXT: -127(nan), 254(3.559298e-43) -; R600-NEXT: 209715200(1.972152e-31), 0(0.000000e+00) -; R600-NEXT: MUL_IEEE T3.X, T1.X, literal.x, -; R600-NEXT: MUL_IEEE T0.Y, PS, literal.y, -; R600-NEXT: CNDE_INT T1.Z, PV.W, PV.Z, T0.Z, -; R600-NEXT: CNDE_INT T3.W, PV.Y, PV.X, T0.X, -; R600-NEXT: SETGT_INT * T4.W, T0.Z, literal.z, -; R600-NEXT: 2130706432(1.701412e+38), 209715200(1.972152e-31) -; R600-NEXT: 127(1.779649e-43), 0(0.000000e+00) -; R600-NEXT: AND_INT T2.Y, KC0[4].X, literal.x, -; R600-NEXT: CNDE_INT T0.Z, PS, PV.Z, PV.W, -; R600-NEXT: CNDE_INT T0.W, T0.W, PV.Y, T2.W, -; R600-NEXT: MUL_IEEE * T2.W, PV.X, literal.y, -; R600-NEXT: -4096(nan), 2130706432(1.701412e+38) -; R600-NEXT: CNDE_INT T0.X, T1.Y, T3.X, PS, -; R600-NEXT: CNDE_INT T0.Y, T1.W, PV.W, T1.X, -; R600-NEXT: LSHL T0.Z, PV.Z, literal.x, -; R600-NEXT: ADD T0.W, KC0[4].X, -PV.Y, -; R600-NEXT: MUL_IEEE * T1.W, PV.Y, literal.y, -; R600-NEXT: 23(3.222986e-44), 1079283712(3.321289e+00) -; R600-NEXT: RNDNE T1.Y, PS, -; R600-NEXT: MUL_IEEE T1.Z, PV.W, literal.x, -; R600-NEXT: ADD_INT T2.W, PV.Z, literal.y, -; R600-NEXT: CNDE_INT * T3.W, T4.W, PV.Y, PV.X, -; R600-NEXT: 975668412(6.390323e-04), 1065353216(1.000000e+00) -; R600-NEXT: MUL_IEEE T0.Y, PS, PV.W, -; R600-NEXT: AND_INT T0.Z, KC0[3].W, literal.x, -; R600-NEXT: MULADD_IEEE T0.W, T0.W, literal.y, PV.Z, -; R600-NEXT: TRUNC * T2.W, PV.Y, -; R600-NEXT: -4096(nan), 1079283712(3.321289e+00) -; R600-NEXT: SETGT T0.X, literal.x, KC0[3].Z, -; R600-NEXT: FLT_TO_INT T3.Y, PS, -; R600-NEXT: MULADD_IEEE T1.Z, T2.Y, literal.y, PV.W, -; R600-NEXT: ADD T0.W, T1.W, -T1.Y, -; R600-NEXT: MUL_IEEE * T1.W, PV.Z, literal.z, -; R600-NEXT: -1036817932(-4.485347e+01), 975668412(6.390323e-04) -; R600-NEXT: 1079283712(3.321289e+00), 0(0.000000e+00) -; R600-NEXT: RNDNE T1.X, PS, -; R600-NEXT: AND_INT T1.Y, KC0[3].Y, literal.x, -; R600-NEXT: ADD T1.Z, PV.W, PV.Z, -; R600-NEXT: MAX_INT T0.W, PV.Y, literal.y, -; R600-NEXT: MIN_INT * T2.W, PV.Y, literal.z, -; R600-NEXT: -4096(nan), -330(nan) +; R600-NEXT: ADD T0.W, PS, PV.W, +; R600-NEXT: TRUNC * T1.W, T4.W, +; R600-NEXT: FLT_TO_INT T1.W, PS, +; R600-NEXT: EXP_IEEE * T0.X, PV.W, +; R600-NEXT: MUL_IEEE T0.Z, PS, literal.x, +; R600-NEXT: MAX_INT T0.W, PV.W, literal.y, +; R600-NEXT: MIN_INT * T2.W, PV.W, literal.z, +; R600-NEXT: 209715200(1.972152e-31), -330(nan) ; R600-NEXT: 381(5.338947e-43), 0(0.000000e+00) -; R600-NEXT: ADD_INT T2.X, PS, literal.x, -; R600-NEXT: ADD_INT T2.Y, PV.W, literal.y, -; R600-NEXT: ADD_INT T2.Z, T3.Y, literal.z, -; R600-NEXT: SETGT_UINT T0.W, T3.Y, literal.w, -; R600-NEXT: EXP_IEEE * T1.Z, PV.Z, -; R600-NEXT: -254(nan), 204(2.858649e-43) -; R600-NEXT: 102(1.429324e-43), -229(nan) -; R600-NEXT: ADD_INT T3.X, T3.Y, literal.x, -; R600-NEXT: SETGT_UINT T4.Y, T3.Y, literal.y, -; R600-NEXT: CNDE_INT T2.Z, PV.W, PV.Y, PV.Z, -; R600-NEXT: SETGT_INT T2.W, T3.Y, literal.x, -; R600-NEXT: MUL_IEEE * T3.W, PS, literal.z, +; R600-NEXT: ADD_INT T1.X, PS, literal.x, +; R600-NEXT: AND_INT T0.Y, KC0[4].X, literal.y, +; R600-NEXT: ADD_INT T1.Z, PV.W, literal.z, +; R600-NEXT: ADD_INT * T0.W, T1.W, literal.w, +; R600-NEXT: -254(nan), -4096(nan) +; R600-NEXT: 204(2.858649e-43), 102(1.429324e-43) +; R600-NEXT: SETGT_UINT * T2.W, T1.W, literal.x, +; R600-NEXT: -229(nan), 0(0.000000e+00) +; R600-NEXT: ADD_INT T2.X, T1.W, literal.x, +; R600-NEXT: SETGT_UINT T1.Y, T1.W, literal.y, +; R600-NEXT: CNDE_INT T1.Z, PV.W, T1.Z, T0.W, +; R600-NEXT: SETGT_INT T0.W, T1.W, literal.x, +; R600-NEXT: ADD * T3.W, KC0[4].X, -T0.Y, ; R600-NEXT: -127(nan), 254(3.559298e-43) -; R600-NEXT: 209715200(1.972152e-31), 0(0.000000e+00) -; R600-NEXT: MUL_IEEE T4.X, T1.Z, literal.x, -; R600-NEXT: MUL_IEEE T2.Y, PS, literal.y, -; R600-NEXT: CNDE_INT T2.Z, PV.W, PV.Z, T3.Y, -; R600-NEXT: CNDE_INT T4.W, PV.Y, PV.X, T2.X, -; R600-NEXT: SETGT_INT * T5.W, T3.Y, literal.z, -; R600-NEXT: 2130706432(1.701412e+38), 209715200(1.972152e-31) +; R600-NEXT: MUL_IEEE T3.X, PS, literal.x, +; R600-NEXT: MUL_IEEE T2.Y, T0.Y, literal.y, +; R600-NEXT: CNDE_INT T1.Z, PV.W, PV.Z, T1.W, +; R600-NEXT: CNDE_INT T4.W, PV.Y, PV.X, T1.X, +; R600-NEXT: SETGT_INT * T1.W, T1.W, literal.z, +; R600-NEXT: 975668412(6.390323e-04), 1079283712(3.321289e+00) ; R600-NEXT: 127(1.779649e-43), 0(0.000000e+00) -; R600-NEXT: ADD T2.X, KC0[3].W, -T0.Z, -; R600-NEXT: CNDE_INT T3.Y, PS, PV.Z, PV.W, -; R600-NEXT: CNDE_INT * T2.Z, T0.W, PV.Y, T3.W, -; R600-NEXT: ALU clause starting at 105: -; R600-NEXT: MUL_IEEE T0.W, T4.X, literal.x, -; R600-NEXT: ADD * T3.W, KC0[3].Y, -T1.Y, +; R600-NEXT: CNDE_INT T1.X, PS, PV.Z, PV.W, +; R600-NEXT: RNDNE T3.Y, PV.Y, +; R600-NEXT: MULADD_IEEE T1.Z, T3.W, literal.x, PV.X, +; R600-NEXT: MUL_IEEE T3.W, T0.Z, literal.y, +; R600-NEXT: MUL_IEEE * T4.W, T0.X, literal.z, +; R600-NEXT: 1079283712(3.321289e+00), 209715200(1.972152e-31) ; R600-NEXT: 2130706432(1.701412e+38), 0(0.000000e+00) +; R600-NEXT: MUL_IEEE T2.X, PS, literal.x, +; R600-NEXT: CNDE_INT T4.Y, T2.W, PV.W, T0.Z, +; R600-NEXT: MULADD_IEEE T0.Z, T0.Y, literal.y, PV.Z, +; R600-NEXT: ADD T2.W, T2.Y, -PV.Y, BS:VEC_120/SCL_212 +; R600-NEXT: AND_INT * T3.W, KC0[3].Y, literal.z, +; R600-NEXT: 2130706432(1.701412e+38), 975668412(6.390323e-04) +; R600-NEXT: -4096(nan), 0(0.000000e+00) ; R600-NEXT: MUL_IEEE T3.X, PS, literal.x, -; R600-NEXT: MUL_IEEE T2.Y, T1.Y, literal.y, -; R600-NEXT: CNDE_INT T3.Z, T4.Y, T4.X, PV.W, BS:VEC_120/SCL_212 -; R600-NEXT: CNDE_INT T0.W, T2.W, T2.Z, T1.Z, -; R600-NEXT: LSHL * T2.W, T3.Y, literal.z, -; R600-NEXT: 975668412(6.390323e-04), 1079283712(3.321289e+00) -; R600-NEXT: 23(3.222986e-44), 0(0.000000e+00) -; R600-NEXT: ADD_INT T4.X, PS, literal.x, -; R600-NEXT: CNDE_INT T3.Y, T5.W, PV.W, PV.Z, -; R600-NEXT: RNDNE T1.Z, PV.Y, -; R600-NEXT: MULADD_IEEE T0.W, T3.W, literal.y, PV.X, BS:VEC_120/SCL_212 -; R600-NEXT: MUL_IEEE * T2.W, T2.X, literal.z, +; R600-NEXT: ADD T0.Y, PV.W, PV.Z, +; R600-NEXT: CNDE_INT T0.Z, T0.W, PV.Y, T0.X, BS:VEC_021/SCL_122 +; R600-NEXT: CNDE_INT T0.W, T1.Y, T4.W, PV.X, +; R600-NEXT: LSHL * T2.W, T1.X, literal.y, +; R600-NEXT: 1079283712(3.321289e+00), 23(3.222986e-44) +; R600-NEXT: AND_INT T0.X, KC0[3].W, literal.x, +; R600-NEXT: TRUNC T1.Y, T3.Y, +; R600-NEXT: ADD_INT T1.Z, PS, literal.y, +; R600-NEXT: CNDE_INT T0.W, T1.W, PV.Z, PV.W, +; R600-NEXT: EXP_IEEE * T0.Y, PV.Y, +; R600-NEXT: -4096(nan), 1065353216(1.000000e+00) +; R600-NEXT: MUL_IEEE T1.X, PV.W, PV.Z, +; R600-NEXT: FLT_TO_INT T1.Y, PV.Y, +; R600-NEXT: MUL_IEEE T0.Z, PS, literal.x, +; R600-NEXT: ADD T0.W, KC0[3].W, -PV.X, +; R600-NEXT: RNDNE * T1.W, T3.X, +; R600-NEXT: 209715200(1.972152e-31), 0(0.000000e+00) +; R600-NEXT: SETGT T2.X, literal.x, KC0[3].Z, +; R600-NEXT: TRUNC T2.Y, PS, +; R600-NEXT: MUL_IEEE T1.Z, PV.W, literal.y, +; R600-NEXT: MUL_IEEE T2.W, PV.Z, literal.z, +; R600-NEXT: MAX_INT * T4.W, PV.Y, literal.w, +; R600-NEXT: -1036817932(-4.485347e+01), 975668412(6.390323e-04) +; R600-NEXT: 209715200(1.972152e-31), -330(nan) +; R600-NEXT: ADD T4.X, KC0[3].Y, -T3.W, +; R600-NEXT: ADD_INT T3.Y, PS, literal.x, +; R600-NEXT: ADD_INT T2.Z, T1.Y, literal.y, +; R600-NEXT: SETGT_UINT T4.W, T1.Y, literal.z, +; R600-NEXT: MIN_INT * T5.W, T1.Y, literal.w, +; R600-NEXT: 204(2.858649e-43), 102(1.429324e-43) +; R600-NEXT: -229(nan), 381(5.338947e-43) +; R600-NEXT: ADD_INT T5.X, PS, literal.x, +; R600-NEXT: ADD_INT T4.Y, T1.Y, literal.y, +; R600-NEXT: SETGT_UINT T3.Z, T1.Y, literal.z, +; R600-NEXT: CNDE_INT T5.W, PV.W, PV.Y, PV.Z, +; R600-NEXT: SETGT_INT * T6.W, T1.Y, literal.y, +; R600-NEXT: -254(nan), -127(nan) +; R600-NEXT: 254(3.559298e-43), 0(0.000000e+00) +; R600-NEXT: MUL_IEEE T6.X, T0.Y, literal.x, +; R600-NEXT: CNDE_INT T3.Y, PS, PV.W, T1.Y, +; R600-NEXT: CNDE_INT * T2.Z, PV.Z, PV.Y, PV.X, +; R600-NEXT: 2130706432(1.701412e+38), 0(0.000000e+00) +; R600-NEXT: ALU clause starting at 105: +; R600-NEXT: SETGT_INT T5.W, T1.Y, literal.x, +; R600-NEXT: MUL_IEEE * T7.W, T4.X, literal.y, +; R600-NEXT: 127(1.779649e-43), 975668412(6.390323e-04) +; R600-NEXT: MUL_IEEE T5.X, T0.X, literal.x, +; R600-NEXT: MULADD_IEEE T1.Y, T4.X, literal.x, PS, BS:VEC_120/SCL_212 +; R600-NEXT: CNDE_INT T2.Z, PV.W, T3.Y, T2.Z, +; R600-NEXT: MUL_IEEE T7.W, T6.X, literal.y, BS:VEC_201 +; R600-NEXT: CNDE_INT * T2.W, T4.W, T2.W, T0.Z, +; R600-NEXT: 1079283712(3.321289e+00), 2130706432(1.701412e+38) +; R600-NEXT: CNDE_INT T4.X, T6.W, PS, T0.Y, +; R600-NEXT: CNDE_INT T0.Y, T3.Z, T6.X, PV.W, +; R600-NEXT: LSHL T0.Z, PV.Z, literal.x, +; R600-NEXT: MULADD_IEEE T2.W, T3.W, literal.y, PV.Y, BS:VEC_201 +; R600-NEXT: ADD * T1.W, T3.X, -T1.W, +; R600-NEXT: 23(3.222986e-44), 975668412(6.390323e-04) +; R600-NEXT: ADD T3.X, PS, PV.W, +; R600-NEXT: ADD_INT T1.Y, PV.Z, literal.x, +; R600-NEXT: CNDE_INT T0.Z, T5.W, PV.X, PV.Y, +; R600-NEXT: RNDNE T1.W, T5.X, +; R600-NEXT: MULADD_IEEE * T0.W, T0.W, literal.y, T1.Z, BS:VEC_021/SCL_122 ; R600-NEXT: 1065353216(1.000000e+00), 1079283712(3.321289e+00) -; R600-NEXT: 975668412(6.390323e-04), 0(0.000000e+00) -; R600-NEXT: MULADD_IEEE T2.X, T2.X, literal.x, PS, -; R600-NEXT: MULADD_IEEE T1.Y, T1.Y, literal.y, PV.W, -; R600-NEXT: ADD T2.Z, T2.Y, -PV.Z, BS:VEC_120/SCL_212 -; R600-NEXT: MUL_IEEE T0.W, PV.Y, PV.X, -; R600-NEXT: SETGT * T2.W, literal.z, KC0[4].X, -; R600-NEXT: 1079283712(3.321289e+00), 975668412(6.390323e-04) -; R600-NEXT: -1036817932(-4.485347e+01), 0(0.000000e+00) -; R600-NEXT: CNDE T3.X, PS, PV.W, 0.0, -; R600-NEXT: ADD T1.Y, PV.Z, PV.Y, -; R600-NEXT: TRUNC T1.Z, T1.Z, -; R600-NEXT: MULADD_IEEE T0.W, T0.Z, literal.x, PV.X, BS:VEC_120/SCL_212 -; R600-NEXT: ADD * T1.W, T1.W, -T1.X, -; R600-NEXT: 975668412(6.390323e-04), 0(0.000000e+00) -; R600-NEXT: SETGT T2.X, KC0[4].X, literal.x, -; R600-NEXT: ADD T2.Y, PS, PV.W, -; R600-NEXT: FLT_TO_INT T0.Z, PV.Z, -; R600-NEXT: TRUNC T0.W, T1.X, -; R600-NEXT: EXP_IEEE * T1.X, PV.Y, -; R600-NEXT: 1109008539(3.853184e+01), 0(0.000000e+00) -; R600-NEXT: MUL_IEEE T4.X, PS, literal.x, -; R600-NEXT: FLT_TO_INT T1.Y, PV.W, -; R600-NEXT: MAX_INT T1.Z, PV.Z, literal.y, -; R600-NEXT: MUL_IEEE T0.W, PS, literal.z, -; R600-NEXT: EXP_IEEE * T1.W, PV.Y, -; R600-NEXT: 2130706432(1.701412e+38), -330(nan) +; R600-NEXT: MULADD_IEEE T0.X, T0.X, literal.x, PS, +; R600-NEXT: ADD T0.Y, T5.X, -PV.W, BS:VEC_120/SCL_212 +; R600-NEXT: MUL_IEEE T0.Z, PV.Z, PV.Y, +; R600-NEXT: SETGT T0.W, literal.y, KC0[4].X, +; R600-NEXT: EXP_IEEE * T1.Y, PV.X, +; R600-NEXT: 975668412(6.390323e-04), -1036817932(-4.485347e+01) +; R600-NEXT: CNDE T3.X, PV.W, PV.Z, 0.0, +; R600-NEXT: ADD T0.Y, PV.Y, PV.X, +; R600-NEXT: FLT_TO_INT T0.Z, T2.Y, +; R600-NEXT: TRUNC T0.W, T1.W, +; R600-NEXT: MUL_IEEE * T1.W, PS, literal.x, ; R600-NEXT: 209715200(1.972152e-31), 0(0.000000e+00) -; R600-NEXT: MUL_IEEE T5.X, PV.W, literal.x, -; R600-NEXT: MUL_IEEE T2.Y, PS, literal.x, -; R600-NEXT: ADD_INT T1.Z, PV.Z, literal.y, -; R600-NEXT: ADD_INT T2.W, T0.Z, literal.z, -; R600-NEXT: MAX_INT * T3.W, PV.Y, literal.w, -; R600-NEXT: 209715200(1.972152e-31), 204(2.858649e-43) -; R600-NEXT: 102(1.429324e-43), -330(nan) -; R600-NEXT: SETGT_UINT T6.X, T0.Z, literal.x, -; R600-NEXT: ADD_INT T3.Y, PS, literal.y, -; R600-NEXT: ADD_INT T2.Z, T1.Y, literal.z, -; R600-NEXT: SETGT_UINT T3.W, T1.Y, literal.x, -; R600-NEXT: MIN_INT * T4.W, T1.Y, literal.w, +; R600-NEXT: SETGT T0.X, KC0[4].X, literal.x, +; R600-NEXT: MUL_IEEE T2.Y, PS, literal.y, +; R600-NEXT: FLT_TO_INT T1.Z, PV.W, +; R600-NEXT: MAX_INT T0.W, PV.Z, literal.z, +; R600-NEXT: EXP_IEEE * T0.Y, PV.Y, +; R600-NEXT: 1109008539(3.853184e+01), 209715200(1.972152e-31) +; R600-NEXT: -330(nan), 0(0.000000e+00) +; R600-NEXT: MUL_IEEE T4.X, T1.Y, literal.x, +; R600-NEXT: MUL_IEEE T3.Y, PS, literal.y, +; R600-NEXT: ADD_INT T2.Z, PV.W, literal.z, +; R600-NEXT: ADD_INT * T0.W, T0.Z, literal.w, +; R600-NEXT: 2130706432(1.701412e+38), 209715200(1.972152e-31) +; R600-NEXT: 204(2.858649e-43), 102(1.429324e-43) +; R600-NEXT: MAX_INT * T2.W, T1.Z, literal.x, +; R600-NEXT: -330(nan), 0(0.000000e+00) +; R600-NEXT: SETGT_UINT T5.X, T0.Z, literal.x, +; R600-NEXT: ADD_INT T4.Y, PV.W, literal.y, +; R600-NEXT: ADD_INT T3.Z, T1.Z, literal.z, BS:VEC_120/SCL_212 +; R600-NEXT: SETGT_UINT T2.W, T1.Z, literal.x, BS:VEC_120/SCL_212 +; R600-NEXT: MIN_INT * T3.W, T1.Z, literal.w, ; R600-NEXT: -229(nan), 204(2.858649e-43) ; R600-NEXT: 102(1.429324e-43), 381(5.338947e-43) -; R600-NEXT: ADD_INT T7.X, PS, literal.x, -; R600-NEXT: ADD_INT T4.Y, T1.Y, literal.y, -; R600-NEXT: SETGT_UINT T3.Z, T1.Y, literal.z, -; R600-NEXT: CNDE_INT T4.W, PV.W, PV.Y, PV.Z, -; R600-NEXT: SETGT_INT * T5.W, T1.Y, literal.y, +; R600-NEXT: ADD_INT T6.X, PS, literal.x, +; R600-NEXT: ADD_INT T5.Y, T1.Z, literal.y, +; R600-NEXT: SETGT_UINT T4.Z, T1.Z, literal.z, +; R600-NEXT: CNDE_INT T3.W, PV.W, PV.Y, PV.Z, +; R600-NEXT: SETGT_INT * T4.W, T1.Z, literal.y, ; R600-NEXT: -254(nan), -127(nan) ; R600-NEXT: 254(3.559298e-43), 0(0.000000e+00) -; R600-NEXT: CNDE_INT T8.X, PS, PV.W, T1.Y, -; R600-NEXT: CNDE_INT T3.Y, PV.Z, PV.Y, PV.X, -; R600-NEXT: SETGT_INT T2.Z, T1.Y, literal.x, -; R600-NEXT: CNDE_INT T2.W, T6.X, T1.Z, T2.W, -; R600-NEXT: SETGT_INT * T4.W, T0.Z, literal.y, +; R600-NEXT: CNDE_INT T7.X, PS, PV.W, T1.Z, BS:VEC_021/SCL_122 +; R600-NEXT: CNDE_INT T4.Y, PV.Z, PV.Y, PV.X, +; R600-NEXT: SETGT_INT T1.Z, T1.Z, literal.x, BS:VEC_120/SCL_212 +; R600-NEXT: CNDE_INT T0.W, T5.X, T2.Z, T0.W, BS:VEC_102/SCL_221 +; R600-NEXT: SETGT_INT * T3.W, T0.Z, literal.y, ; R600-NEXT: 127(1.779649e-43), -127(nan) -; R600-NEXT: CNDE_INT T7.X, PS, PV.W, T0.Z, -; R600-NEXT: CNDE_INT T1.Y, PV.Z, PV.X, PV.Y, -; R600-NEXT: MIN_INT T1.Z, T0.Z, literal.x, -; R600-NEXT: MUL_IEEE T2.W, T1.W, literal.y, -; R600-NEXT: MUL_IEEE * T6.W, T2.Y, literal.z, -; R600-NEXT: 381(5.338947e-43), 2130706432(1.701412e+38) -; R600-NEXT: 209715200(1.972152e-31), 0(0.000000e+00) -; R600-NEXT: CNDE_INT T8.X, T3.W, PS, T2.Y, -; R600-NEXT: MUL_IEEE T2.Y, PV.W, literal.x, -; R600-NEXT: ADD_INT T1.Z, PV.Z, literal.y, -; R600-NEXT: ADD_INT T3.W, T0.Z, literal.z, -; R600-NEXT: SETGT_UINT * T6.W, T0.Z, literal.w, +; R600-NEXT: CNDE_INT T6.X, PS, PV.W, T0.Z, +; R600-NEXT: CNDE_INT T4.Y, PV.Z, PV.X, PV.Y, +; R600-NEXT: MIN_INT T2.Z, T0.Z, literal.x, +; R600-NEXT: MUL_IEEE T0.W, T3.Y, literal.y, +; R600-NEXT: MUL_IEEE * T5.W, T0.Y, literal.z, +; R600-NEXT: 381(5.338947e-43), 209715200(1.972152e-31) +; R600-NEXT: 2130706432(1.701412e+38), 0(0.000000e+00) +; R600-NEXT: MUL_IEEE T7.X, PS, literal.x, +; R600-NEXT: CNDE_INT T3.Y, T2.W, PV.W, T3.Y, +; R600-NEXT: ADD_INT T2.Z, PV.Z, literal.y, +; R600-NEXT: ADD_INT T0.W, T0.Z, literal.z, +; R600-NEXT: SETGT_UINT * T2.W, T0.Z, literal.w, ; R600-NEXT: 2130706432(1.701412e+38), -254(nan) ; R600-NEXT: -127(nan), 254(3.559298e-43) -; R600-NEXT: CNDE_INT T9.X, PS, PV.W, PV.Z, -; R600-NEXT: SETGT_INT T3.Y, T0.Z, literal.x, -; R600-NEXT: CNDE_INT T0.Z, T3.Z, T2.W, PV.Y, BS:VEC_120/SCL_212 -; R600-NEXT: CNDE_INT T1.W, T5.W, PV.X, T1.W, BS:VEC_021/SCL_122 -; R600-NEXT: LSHL * T2.W, T1.Y, literal.y, +; R600-NEXT: CNDE_INT T8.X, PS, PV.W, PV.Z, +; R600-NEXT: SETGT_INT T5.Y, T0.Z, literal.x, +; R600-NEXT: CNDE_INT T0.Z, T4.W, PV.Y, T0.Y, BS:VEC_021/SCL_122 +; R600-NEXT: CNDE_INT T0.W, T4.Z, T5.W, PV.X, BS:VEC_120/SCL_212 +; R600-NEXT: LSHL * T4.W, T4.Y, literal.y, ; R600-NEXT: 127(1.779649e-43), 23(3.222986e-44) -; R600-NEXT: ADD_INT T8.X, PS, literal.x, -; R600-NEXT: CNDE_INT T1.Y, T2.Z, PV.W, PV.Z, -; R600-NEXT: CNDE_INT T0.Z, PV.Y, T7.X, PV.X, -; R600-NEXT: CNDE_INT * T0.W, T6.X, T5.X, T0.W, BS:VEC_021/SCL_122 -; R600-NEXT: 1065353216(1.000000e+00), 0(0.000000e+00) -; R600-NEXT: MUL_IEEE * T1.W, T4.X, literal.x, -; R600-NEXT: 2130706432(1.701412e+38), 0(0.000000e+00) -; R600-NEXT: CNDE_INT T4.X, T6.W, T4.X, PV.W, -; R600-NEXT: CNDE_INT * T2.Y, T4.W, T0.W, T1.X, BS:VEC_120/SCL_212 -; R600-NEXT: ALU clause starting at 204: +; R600-NEXT: ADD_INT T7.X, PS, literal.x, +; R600-NEXT: CNDE_INT T0.Y, T1.Z, PV.Z, PV.W, +; R600-NEXT: CNDE_INT T0.Z, PV.Y, T6.X, PV.X, +; R600-NEXT: MUL_IEEE T0.W, T4.X, literal.y, +; R600-NEXT: CNDE_INT * T1.W, T5.X, T2.Y, T1.W, +; R600-NEXT: 1065353216(1.000000e+00), 2130706432(1.701412e+38) +; R600-NEXT: CNDE_INT T5.X, T3.W, PS, T1.Y, +; R600-NEXT: CNDE_INT * T1.Y, T2.W, T4.X, PV.W, BS:VEC_120/SCL_212 +; R600-NEXT: ALU clause starting at 201: ; R600-NEXT: LSHL T0.Z, T0.Z, literal.x, -; R600-NEXT: MUL_IEEE T0.W, T1.Y, T8.X, +; R600-NEXT: MUL_IEEE T0.W, T0.Y, T7.X, ; R600-NEXT: SETGT * T1.W, literal.y, KC0[3].W, ; R600-NEXT: 23(3.222986e-44), -1036817932(-4.485347e+01) -; R600-NEXT: CNDE T1.X, PS, PV.W, 0.0, -; R600-NEXT: SETGT T1.Y, KC0[3].W, literal.x, +; R600-NEXT: CNDE T4.X, PS, PV.W, 0.0, +; R600-NEXT: SETGT T0.Y, KC0[3].W, literal.x, ; R600-NEXT: ADD_INT T0.Z, PV.Z, literal.y, -; R600-NEXT: CNDE_INT T0.W, T3.Y, T2.Y, T4.X, BS:VEC_120/SCL_212 -; R600-NEXT: CNDE * T1.W, T2.X, T3.X, literal.z, +; R600-NEXT: CNDE_INT T0.W, T5.Y, T5.X, T1.Y, BS:VEC_102/SCL_221 +; R600-NEXT: CNDE * T1.W, T0.X, T3.X, literal.z, ; R600-NEXT: 1109008539(3.853184e+01), 1065353216(1.000000e+00) ; R600-NEXT: 2139095040(INF), 0(0.000000e+00) -; R600-NEXT: MUL_IEEE T2.X, PV.W, PV.Z, +; R600-NEXT: MUL_IEEE T0.X, PV.W, PV.Z, ; R600-NEXT: SETGT T2.Y, literal.x, KC0[3].Y, ; R600-NEXT: CNDE T1.Z, PV.Y, PV.X, literal.y, -; R600-NEXT: CNDE T0.W, T0.X, T0.Y, 0.0, +; R600-NEXT: CNDE T0.W, T2.X, T1.X, 0.0, ; R600-NEXT: SETGT * T2.W, KC0[3].Z, literal.z, ; R600-NEXT: -1036817932(-4.485347e+01), 2139095040(INF) ; R600-NEXT: 1109008539(3.853184e+01), 0(0.000000e+00) @@ -2287,8 +2275,8 @@ define amdgpu_kernel void @s_exp10_v4f32(ptr addrspace(1) %out, <4 x float> %in) ; CM-LABEL: s_exp10_v4f32: ; CM: ; %bb.0: ; CM-NEXT: ALU 97, @6, KC0[CB0:0-32], KC1[] -; CM-NEXT: ALU 100, @104, KC0[CB0:0-32], KC1[] -; CM-NEXT: ALU 36, @205, KC0[CB0:0-32], KC1[] +; CM-NEXT: ALU 97, @104, KC0[CB0:0-32], KC1[] +; CM-NEXT: ALU 35, @202, KC0[CB0:0-32], KC1[] ; CM-NEXT: MEM_RAT_CACHELESS STORE_DWORD T0, T1.X ; CM-NEXT: CF_END ; CM-NEXT: PAD @@ -2307,224 +2295,220 @@ define amdgpu_kernel void @s_exp10_v4f32(ptr addrspace(1) %out, <4 x float> %in) ; CM-NEXT: 1079283712(3.321289e+00), 0(0.000000e+00) ; CM-NEXT: MULADD_IEEE T0.X, T0.W, literal.x, PV.W, ; CM-NEXT: ADD T0.Y, T0.Z, -PV.Z, -; CM-NEXT: MUL_IEEE T0.Z, PV.Y, literal.x, -; CM-NEXT: MUL_IEEE * T0.W, T2.W, literal.y, BS:VEC_120/SCL_212 +; CM-NEXT: MUL_IEEE T0.Z, T2.W, literal.y, BS:VEC_120/SCL_212 +; CM-NEXT: MUL_IEEE * T0.W, PV.Y, literal.x, ; CM-NEXT: 975668412(6.390323e-04), 1079283712(3.321289e+00) ; CM-NEXT: TRUNC T1.X, T1.Z, -; CM-NEXT: RNDNE T2.Y, PV.W, -; CM-NEXT: MULADD_IEEE T0.Z, T1.Y, literal.x, PV.Z, -; CM-NEXT: ADD * T1.W, PV.Y, PV.X, +; CM-NEXT: MULADD_IEEE T1.Y, T1.Y, literal.x, PV.W, +; CM-NEXT: RNDNE T1.Z, PV.Z, +; CM-NEXT: ADD * T0.W, PV.Y, PV.X, ; CM-NEXT: 1079283712(3.321289e+00), 0(0.000000e+00) +; CM-NEXT: EXP_IEEE T0.X, T0.W, +; CM-NEXT: EXP_IEEE T0.Y (MASKED), T0.W, +; CM-NEXT: EXP_IEEE T0.Z (MASKED), T0.W, +; CM-NEXT: EXP_IEEE * T0.W (MASKED), T0.W, +; CM-NEXT: TRUNC T2.X, T1.Z, +; CM-NEXT: MULADD_IEEE T0.Y, T2.W, literal.x, T1.Y, +; CM-NEXT: FLT_TO_INT T2.Z, T1.X, +; CM-NEXT: MUL_IEEE * T0.W, PV.X, literal.y, +; CM-NEXT: 975668412(6.390323e-04), 209715200(1.972152e-31) +; CM-NEXT: ADD T1.X, T0.Z, -T1.Z, +; CM-NEXT: MUL_IEEE T1.Y, PV.W, literal.x, +; CM-NEXT: MAX_INT T0.Z, PV.Z, literal.y, +; CM-NEXT: MIN_INT * T1.W, PV.Z, literal.z, +; CM-NEXT: 209715200(1.972152e-31), -330(nan) +; CM-NEXT: 381(5.338947e-43), 0(0.000000e+00) +; CM-NEXT: ADD_INT T3.X, PV.W, literal.x, +; CM-NEXT: ADD_INT T2.Y, PV.Z, literal.y, +; CM-NEXT: ADD_INT T0.Z, T2.Z, literal.z, +; CM-NEXT: SETGT_UINT * T1.W, T2.Z, literal.w, +; CM-NEXT: -254(nan), 204(2.858649e-43) +; CM-NEXT: 102(1.429324e-43), -229(nan) +; CM-NEXT: ADD_INT T4.X, T2.Z, literal.x, +; CM-NEXT: SETGT_UINT T3.Y, T2.Z, literal.y, +; CM-NEXT: CNDE_INT T0.Z, PV.W, PV.Y, PV.Z, +; CM-NEXT: SETGT_INT * T2.W, T2.Z, literal.x, +; CM-NEXT: -127(nan), 254(3.559298e-43) +; CM-NEXT: MUL_IEEE T5.X, T0.X, literal.x, +; CM-NEXT: CNDE_INT T2.Y, PV.W, PV.Z, T2.Z, +; CM-NEXT: CNDE_INT T0.Z, PV.Y, PV.X, T3.X, +; CM-NEXT: SETGT_INT * T3.W, T2.Z, literal.y, +; CM-NEXT: 2130706432(1.701412e+38), 127(1.779649e-43) +; CM-NEXT: AND_INT T3.X, KC0[3].Z, literal.x, +; CM-NEXT: CNDE_INT T2.Y, PV.W, PV.Y, PV.Z, +; CM-NEXT: MUL_IEEE T0.Z, PV.X, literal.y, +; CM-NEXT: CNDE_INT * T0.W, T1.W, T1.Y, T0.W, +; CM-NEXT: -4096(nan), 2130706432(1.701412e+38) +; CM-NEXT: CNDE_INT T0.X, T2.W, PV.W, T0.X, +; CM-NEXT: CNDE_INT T1.Y, T3.Y, T5.X, PV.Z, +; CM-NEXT: LSHL T0.Z, PV.Y, literal.x, +; CM-NEXT: MUL_IEEE * T0.W, PV.X, literal.y, +; CM-NEXT: 23(3.222986e-44), 1079283712(3.321289e+00) +; CM-NEXT: RNDNE T4.X, PV.W, +; CM-NEXT: ADD_INT T2.Y, PV.Z, literal.x, +; CM-NEXT: CNDE_INT T0.Z, T3.W, PV.X, PV.Y, +; CM-NEXT: ADD * T1.W, T1.X, T0.Y, +; CM-NEXT: 1065353216(1.000000e+00), 0(0.000000e+00) ; CM-NEXT: EXP_IEEE T0.X, T1.W, ; CM-NEXT: EXP_IEEE T0.Y (MASKED), T1.W, ; CM-NEXT: EXP_IEEE T0.Z (MASKED), T1.W, ; CM-NEXT: EXP_IEEE * T0.W (MASKED), T1.W, -; CM-NEXT: MULADD_IEEE T2.X, T2.W, literal.x, T0.Z, -; CM-NEXT: ADD T0.Y, T0.W, -T2.Y, BS:VEC_120/SCL_212 -; CM-NEXT: FLT_TO_INT T0.Z, T1.X, -; CM-NEXT: MUL_IEEE * T0.W, PV.X, literal.y, -; CM-NEXT: 975668412(6.390323e-04), 209715200(1.972152e-31) -; CM-NEXT: MUL_IEEE T1.X, PV.W, literal.x, +; CM-NEXT: MUL_IEEE T1.X, T0.Z, T2.Y, +; CM-NEXT: TRUNC T0.Y, T4.X, +; CM-NEXT: FLT_TO_INT T0.Z, T2.X, BS:VEC_120/SCL_212 +; CM-NEXT: MUL_IEEE * T1.W, PV.X, literal.x, +; CM-NEXT: 209715200(1.972152e-31), 0(0.000000e+00) +; CM-NEXT: MUL_IEEE T2.X, PV.W, literal.x, ; CM-NEXT: MUL_IEEE T1.Y, T0.X, literal.y, ; CM-NEXT: MAX_INT T1.Z, PV.Z, literal.z, -; CM-NEXT: MIN_INT * T1.W, PV.Z, literal.w, +; CM-NEXT: MIN_INT * T2.W, PV.Z, literal.w, ; CM-NEXT: 209715200(1.972152e-31), 2130706432(1.701412e+38) ; CM-NEXT: -330(nan), 381(5.338947e-43) -; CM-NEXT: ADD_INT T3.X, PV.W, literal.x, -; CM-NEXT: ADD_INT T3.Y, PV.Z, literal.y, +; CM-NEXT: ADD_INT T5.X, PV.W, literal.x, +; CM-NEXT: ADD_INT T2.Y, PV.Z, literal.y, ; CM-NEXT: ADD_INT T1.Z, T0.Z, literal.z, -; CM-NEXT: SETGT_UINT * T1.W, T0.Z, literal.w, +; CM-NEXT: SETGT_UINT * T2.W, T0.Z, literal.w, ; CM-NEXT: -254(nan), 204(2.858649e-43) ; CM-NEXT: 102(1.429324e-43), -229(nan) -; CM-NEXT: ADD_INT T4.X, T0.Z, literal.x, -; CM-NEXT: SETGT_UINT T4.Y, T0.Z, literal.y, +; CM-NEXT: ADD_INT T6.X, T0.Z, literal.x, +; CM-NEXT: SETGT_UINT T3.Y, T0.Z, literal.y, ; CM-NEXT: CNDE_INT T1.Z, PV.W, PV.Y, PV.Z, -; CM-NEXT: SETGT_INT * T2.W, T0.Z, literal.x, +; CM-NEXT: SETGT_INT * T3.W, T0.Z, literal.x, ; CM-NEXT: -127(nan), 254(3.559298e-43) -; CM-NEXT: CNDE_INT T5.X, PV.W, PV.Z, T0.Z, -; CM-NEXT: CNDE_INT T3.Y, PV.Y, PV.X, T3.X, -; CM-NEXT: SETGT_INT T0.Z, T0.Z, literal.x, -; CM-NEXT: MUL_IEEE * T3.W, T1.Y, literal.y, -; CM-NEXT: 127(1.779649e-43), 2130706432(1.701412e+38) -; CM-NEXT: CNDE_INT T3.X, T4.Y, T1.Y, PV.W, -; CM-NEXT: AND_INT T1.Y, KC0[3].Z, literal.x, -; CM-NEXT: CNDE_INT T1.Z, PV.Z, PV.X, PV.Y, -; CM-NEXT: CNDE_INT * T0.W, T1.W, T1.X, T0.W, -; CM-NEXT: -4096(nan), 0(0.000000e+00) -; CM-NEXT: CNDE_INT T0.X, T2.W, PV.W, T0.X, -; CM-NEXT: LSHL T3.Y, PV.Z, literal.x, -; CM-NEXT: TRUNC T1.Z, T2.Y, -; CM-NEXT: ADD * T0.W, KC0[3].Z, -PV.Y, -; CM-NEXT: 23(3.222986e-44), 0(0.000000e+00) -; CM-NEXT: MUL_IEEE T1.X, PV.W, literal.x, -; CM-NEXT: FLT_TO_INT T2.Y, PV.Z, -; CM-NEXT: ADD_INT T1.Z, PV.Y, literal.y, -; CM-NEXT: CNDE_INT * T1.W, T0.Z, PV.X, T3.X, -; CM-NEXT: 975668412(6.390323e-04), 1065353216(1.000000e+00) -; CM-NEXT: MUL_IEEE T0.X, PV.W, PV.Z, -; CM-NEXT: MIN_INT T3.Y, PV.Y, literal.x, -; CM-NEXT: MULADD_IEEE T0.Z, T0.W, literal.y, PV.X, -; CM-NEXT: ADD * T0.W, T0.Y, T2.X, -; CM-NEXT: 381(5.338947e-43), 1079283712(3.321289e+00) -; CM-NEXT: EXP_IEEE T0.X (MASKED), T0.W, -; CM-NEXT: EXP_IEEE T0.Y, T0.W, -; CM-NEXT: EXP_IEEE T0.Z (MASKED), T0.W, -; CM-NEXT: EXP_IEEE * T0.W (MASKED), T0.W, -; CM-NEXT: MULADD_IEEE T1.X, T1.Y, literal.x, T0.Z, -; CM-NEXT: MUL_IEEE T4.Y, PV.Y, literal.y, -; CM-NEXT: ADD_INT T0.Z, T3.Y, literal.z, BS:VEC_120/SCL_212 -; CM-NEXT: MAX_INT * T0.W, T2.Y, literal.w, BS:VEC_201 -; CM-NEXT: 975668412(6.390323e-04), 2130706432(1.701412e+38) -; CM-NEXT: -254(nan), -330(nan) -; CM-NEXT: ADD_INT T2.X, T2.Y, literal.x, -; CM-NEXT: ADD_INT T3.Y, PV.W, literal.y, -; CM-NEXT: ADD_INT T1.Z, T2.Y, literal.z, -; CM-NEXT: SETGT_UINT * T0.W, T2.Y, literal.w, -; CM-NEXT: -127(nan), 204(2.858649e-43) -; CM-NEXT: 102(1.429324e-43), -229(nan) -; CM-NEXT: SETGT_UINT T3.X, T2.Y, literal.x, -; CM-NEXT: CNDE_INT T3.Y, PV.W, PV.Y, PV.Z, -; CM-NEXT: SETGT_INT T1.Z, T2.Y, literal.y, -; CM-NEXT: MUL_IEEE * T1.W, T0.Y, literal.z, BS:VEC_120/SCL_212 -; CM-NEXT: 254(3.559298e-43), -127(nan) -; CM-NEXT: 209715200(1.972152e-31), 0(0.000000e+00) -; CM-NEXT: MUL_IEEE T4.X, PV.W, literal.x, -; CM-NEXT: CNDE_INT * T3.Y, PV.Z, PV.Y, T2.Y, -; CM-NEXT: 209715200(1.972152e-31), 0(0.000000e+00) -; CM-NEXT: ALU clause starting at 104: -; CM-NEXT: CNDE_INT T0.Z, T3.X, T2.X, T0.Z, -; CM-NEXT: SETGT_INT * T2.W, T2.Y, literal.x, +; CM-NEXT: CNDE_INT T7.X, PV.W, PV.Z, T0.Z, +; CM-NEXT: CNDE_INT T2.Y, PV.Y, PV.X, T5.X, +; CM-NEXT: SETGT_INT * T0.Z, T0.Z, literal.x, ; CM-NEXT: 127(1.779649e-43), 0(0.000000e+00) -; CM-NEXT: MUL_IEEE T2.X, T1.Y, literal.x, -; CM-NEXT: CNDE_INT T1.Y, PV.W, T3.Y, PV.Z, -; CM-NEXT: CNDE_INT T0.Z, T0.W, T4.X, T1.W, -; CM-NEXT: MUL_IEEE * T0.W, T4.Y, literal.y, BS:VEC_201 -; CM-NEXT: 1079283712(3.321289e+00), 2130706432(1.701412e+38) -; CM-NEXT: AND_INT T4.X, KC0[4].X, literal.x, -; CM-NEXT: CNDE_INT T2.Y, T3.X, T4.Y, PV.W, -; CM-NEXT: CNDE_INT T0.Z, T1.Z, PV.Z, T0.Y, -; CM-NEXT: LSHL * T0.W, PV.Y, literal.y, -; CM-NEXT: -4096(nan), 23(3.222986e-44) -; CM-NEXT: ADD_INT T3.X, PV.W, literal.x, -; CM-NEXT: CNDE_INT T0.Y, T2.W, PV.Z, PV.Y, -; CM-NEXT: MUL_IEEE T0.Z, PV.X, literal.y, -; CM-NEXT: RNDNE * T0.W, T2.X, -; CM-NEXT: 1065353216(1.000000e+00), 1079283712(3.321289e+00) -; CM-NEXT: ADD T2.X, T2.X, -PV.W, -; CM-NEXT: RNDNE T1.Y, PV.Z, -; CM-NEXT: MUL_IEEE T1.Z, PV.Y, PV.X, -; CM-NEXT: SETGT * T1.W, literal.x, KC0[3].W, -; CM-NEXT: -1036817932(-4.485347e+01), 0(0.000000e+00) -; CM-NEXT: CNDE T3.X, PV.W, PV.Z, 0.0, -; CM-NEXT: TRUNC T0.Y, T0.W, -; CM-NEXT: TRUNC T1.Z, PV.Y, -; CM-NEXT: ADD * T0.W, PV.X, T1.X, +; CM-NEXT: ALU clause starting at 104: +; CM-NEXT: ADD * T4.W, KC0[3].Z, -T3.X, +; CM-NEXT: MUL_IEEE T5.X, PV.W, literal.x, +; CM-NEXT: CNDE_INT T2.Y, T0.Z, T7.X, T2.Y, +; CM-NEXT: MUL_IEEE T1.Z, T1.Y, literal.y, +; CM-NEXT: CNDE_INT * T1.W, T2.W, T2.X, T1.W, BS:VEC_021/SCL_122 +; CM-NEXT: 975668412(6.390323e-04), 2130706432(1.701412e+38) +; CM-NEXT: CNDE_INT T0.X, T3.W, PV.W, T0.X, +; CM-NEXT: CNDE_INT T1.Y, T3.Y, T1.Y, PV.Z, +; CM-NEXT: LSHL T1.Z, PV.Y, literal.x, +; CM-NEXT: MULADD_IEEE * T1.W, T4.W, literal.y, PV.X, BS:VEC_120/SCL_212 +; CM-NEXT: 23(3.222986e-44), 1079283712(3.321289e+00) +; CM-NEXT: MULADD_IEEE T2.X, T3.X, literal.x, PV.W, +; CM-NEXT: ADD T2.Y, T0.W, -T4.X, +; CM-NEXT: ADD_INT T1.Z, PV.Z, literal.y, +; CM-NEXT: CNDE_INT * T0.W, T0.Z, PV.X, PV.Y, +; CM-NEXT: 975668412(6.390323e-04), 1065353216(1.000000e+00) +; CM-NEXT: AND_INT T0.X, KC0[4].X, literal.x, +; CM-NEXT: MUL_IEEE T1.Y, PV.W, PV.Z, +; CM-NEXT: SETGT T0.Z, literal.y, KC0[3].W, +; CM-NEXT: ADD * T0.W, PV.Y, PV.X, +; CM-NEXT: -4096(nan), -1036817932(-4.485347e+01) ; CM-NEXT: EXP_IEEE T0.X (MASKED), T0.W, ; CM-NEXT: EXP_IEEE T0.Y (MASKED), T0.W, ; CM-NEXT: EXP_IEEE T0.Z (MASKED), T0.W, ; CM-NEXT: EXP_IEEE * T0.W, T0.W, -; CM-NEXT: FLT_TO_INT T1.X, T1.Z, -; CM-NEXT: FLT_TO_INT T0.Y, T0.Y, -; CM-NEXT: MUL_IEEE T1.Z, PV.W, literal.x, -; CM-NEXT: ADD * T1.W, KC0[4].X, -T4.X, -; CM-NEXT: 2130706432(1.701412e+38), 0(0.000000e+00) -; CM-NEXT: MUL_IEEE T2.X, PV.W, literal.x, -; CM-NEXT: MUL_IEEE T2.Y, T0.W, literal.y, -; CM-NEXT: MUL_IEEE T2.Z, PV.Z, literal.z, -; CM-NEXT: SETGT_UINT * T2.W, PV.Y, literal.w, -; CM-NEXT: 975668412(6.390323e-04), 209715200(1.972152e-31) -; CM-NEXT: 2130706432(1.701412e+38), 254(3.559298e-43) -; CM-NEXT: CNDE_INT T5.X, PV.W, T1.Z, PV.Z, -; CM-NEXT: MUL_IEEE T3.Y, PV.Y, literal.x, -; CM-NEXT: MULADD_IEEE T1.Z, T1.W, literal.y, PV.X, -; CM-NEXT: MAX_INT * T1.W, T1.X, literal.z, -; CM-NEXT: 209715200(1.972152e-31), 1079283712(3.321289e+00) -; CM-NEXT: -330(nan), 0(0.000000e+00) -; CM-NEXT: ADD_INT T2.X, PV.W, literal.x, -; CM-NEXT: ADD_INT T4.Y, T1.X, literal.y, -; CM-NEXT: MULADD_IEEE T1.Z, T4.X, literal.z, PV.Z, BS:VEC_120/SCL_212 -; CM-NEXT: MAX_INT * T1.W, T0.Y, literal.w, -; CM-NEXT: 204(2.858649e-43), 102(1.429324e-43) +; CM-NEXT: CNDE T2.X, T0.Z, T1.Y, 0.0, +; CM-NEXT: ADD T1.Y, KC0[4].X, -T0.X, +; CM-NEXT: FLT_TO_INT T0.Z, T0.Y, +; CM-NEXT: MUL_IEEE * T1.W, PV.W, literal.x, +; CM-NEXT: 209715200(1.972152e-31), 0(0.000000e+00) +; CM-NEXT: MUL_IEEE T3.X, PV.W, literal.x, +; CM-NEXT: SETGT_UINT T0.Y, PV.Z, literal.y, +; CM-NEXT: MUL_IEEE T1.Z, PV.Y, literal.z, +; CM-NEXT: MUL_IEEE * T2.W, T0.X, literal.w, +; CM-NEXT: 209715200(1.972152e-31), -229(nan) +; CM-NEXT: 975668412(6.390323e-04), 1079283712(3.321289e+00) +; CM-NEXT: RNDNE T4.X, PV.W, +; CM-NEXT: MULADD_IEEE T1.Y, T1.Y, literal.x, PV.Z, +; CM-NEXT: CNDE_INT T1.Z, PV.Y, PV.X, T1.W, +; CM-NEXT: SETGT_INT * T1.W, T0.Z, literal.y, +; CM-NEXT: 1079283712(3.321289e+00), -127(nan) +; CM-NEXT: CNDE_INT T3.X, PV.W, PV.Z, T0.W, +; CM-NEXT: MULADD_IEEE T1.Y, T0.X, literal.x, PV.Y, +; CM-NEXT: ADD T1.Z, T2.W, -PV.X, +; CM-NEXT: MAX_INT * T2.W, T0.Z, literal.y, ; CM-NEXT: 975668412(6.390323e-04), -330(nan) -; CM-NEXT: ADD T4.X, T0.Z, -T1.Y, -; CM-NEXT: ADD_INT T1.Y, PV.W, literal.x, -; CM-NEXT: ADD_INT T0.Z, T0.Y, literal.y, -; CM-NEXT: SETGT_UINT * T1.W, T0.Y, literal.z, +; CM-NEXT: ADD_INT T0.X, PV.W, literal.x, +; CM-NEXT: ADD_INT T2.Y, T0.Z, literal.y, +; CM-NEXT: TRUNC T2.Z, T4.X, +; CM-NEXT: ADD * T2.W, PV.Z, PV.Y, ; CM-NEXT: 204(2.858649e-43), 102(1.429324e-43) -; CM-NEXT: -229(nan), 0(0.000000e+00) -; CM-NEXT: SETGT_UINT T6.X, T1.X, literal.x, -; CM-NEXT: CNDE_INT T1.Y, PV.W, PV.Y, PV.Z, -; CM-NEXT: SETGT_INT T0.Z, T0.Y, literal.y, -; CM-NEXT: ADD * T3.W, PV.X, T1.Z, -; CM-NEXT: -229(nan), -127(nan) -; CM-NEXT: EXP_IEEE T1.X (MASKED), T3.W, -; CM-NEXT: EXP_IEEE T1.Y (MASKED), T3.W, -; CM-NEXT: EXP_IEEE T1.Z, T3.W, -; CM-NEXT: EXP_IEEE * T1.W (MASKED), T3.W, -; CM-NEXT: CNDE_INT T4.X, T0.Z, T1.Y, T0.Y, -; CM-NEXT: CNDE_INT T1.Y, T6.X, T2.X, T4.Y, BS:VEC_120/SCL_212 -; CM-NEXT: SETGT_INT T2.Z, T1.X, literal.x, -; CM-NEXT: MUL_IEEE * T3.W, PV.Z, literal.y, -; CM-NEXT: -127(nan), 209715200(1.972152e-31) -; CM-NEXT: MUL_IEEE T2.X, T1.Z, literal.x, -; CM-NEXT: MUL_IEEE T4.Y, PV.W, literal.y, -; CM-NEXT: CNDE_INT T3.Z, PV.Z, PV.Y, T1.X, -; CM-NEXT: MIN_INT * T4.W, T1.X, literal.z, +; CM-NEXT: EXP_IEEE T1.X (MASKED), T2.W, +; CM-NEXT: EXP_IEEE T1.Y, T2.W, +; CM-NEXT: EXP_IEEE T1.Z (MASKED), T2.W, +; CM-NEXT: EXP_IEEE * T1.W (MASKED), T2.W, +; CM-NEXT: MUL_IEEE T4.X, T0.W, literal.x, +; CM-NEXT: FLT_TO_INT T3.Y, T2.Z, +; CM-NEXT: MUL_IEEE T1.Z, PV.Y, literal.y, +; CM-NEXT: CNDE_INT * T0.W, T0.Y, T0.X, T2.Y, ; CM-NEXT: 2130706432(1.701412e+38), 209715200(1.972152e-31) +; CM-NEXT: CNDE_INT T0.X, T1.W, PV.W, T0.Z, +; CM-NEXT: MUL_IEEE T0.Y, PV.Z, literal.x, +; CM-NEXT: MAX_INT T2.Z, PV.Y, literal.y, +; CM-NEXT: MIN_INT * T0.W, PV.Y, literal.z, +; CM-NEXT: 209715200(1.972152e-31), -330(nan) ; CM-NEXT: 381(5.338947e-43), 0(0.000000e+00) -; CM-NEXT: MIN_INT T7.X, T0.Y, literal.x, -; CM-NEXT: ADD_INT T1.Y, PV.W, literal.y, -; CM-NEXT: ADD_INT T4.Z, T1.X, literal.z, -; CM-NEXT: SETGT_UINT * T4.W, T1.X, literal.w, -; CM-NEXT: 381(5.338947e-43), -254(nan) +; CM-NEXT: ADD_INT T5.X, PV.W, literal.x, +; CM-NEXT: ADD_INT T2.Y, PV.Z, literal.y, +; CM-NEXT: ADD_INT T2.Z, T3.Y, literal.z, +; CM-NEXT: SETGT_UINT * T0.W, T3.Y, literal.w, +; CM-NEXT: -254(nan), 204(2.858649e-43) +; CM-NEXT: 102(1.429324e-43), -229(nan) +; CM-NEXT: ADD_INT T6.X, T3.Y, literal.x, +; CM-NEXT: SETGT_UINT T4.Y, T3.Y, literal.y, +; CM-NEXT: CNDE_INT T2.Z, PV.W, PV.Y, PV.Z, +; CM-NEXT: SETGT_INT * T1.W, T3.Y, literal.x, ; CM-NEXT: -127(nan), 254(3.559298e-43) -; CM-NEXT: CNDE_INT T8.X, PV.W, PV.Z, PV.Y, -; CM-NEXT: SETGT_INT T1.Y, T1.X, literal.x, -; CM-NEXT: ADD_INT T4.Z, PV.X, literal.y, -; CM-NEXT: ADD_INT * T5.W, T0.Y, literal.z, +; CM-NEXT: MUL_IEEE T7.X, T1.Y, literal.x, +; CM-NEXT: CNDE_INT T2.Y, PV.W, PV.Z, T3.Y, +; CM-NEXT: CNDE_INT T2.Z, PV.Y, PV.X, T5.X, +; CM-NEXT: MIN_INT * T2.W, T0.Z, literal.y, +; CM-NEXT: 2130706432(1.701412e+38), 381(5.338947e-43) +; CM-NEXT: SETGT_INT T5.X, T3.Y, literal.x, +; CM-NEXT: ADD_INT T3.Y, PV.W, literal.y, +; CM-NEXT: ADD_INT T3.Z, T0.Z, literal.z, +; CM-NEXT: SETGT_UINT * T2.W, T0.Z, literal.w, ; CM-NEXT: 127(1.779649e-43), -254(nan) -; CM-NEXT: -127(nan), 0(0.000000e+00) -; CM-NEXT: CNDE_INT T1.X, T2.W, PV.W, PV.Z, -; CM-NEXT: CNDE_INT T5.Y, PV.Y, T3.Z, PV.X, -; CM-NEXT: CNDE_INT T3.Z, T6.X, T4.Y, T3.W, -; CM-NEXT: MUL_IEEE * T2.W, T2.X, literal.x, BS:VEC_120/SCL_212 +; CM-NEXT: -127(nan), 254(3.559298e-43) +; CM-NEXT: CNDE_INT T6.X, PV.W, PV.Z, PV.Y, +; CM-NEXT: CNDE_INT T2.Y, PV.X, T2.Y, T2.Z, +; CM-NEXT: MUL_IEEE T2.Z, T7.X, literal.x, +; CM-NEXT: CNDE_INT * T0.W, T0.W, T0.Y, T1.Z, BS:VEC_021/SCL_122 ; CM-NEXT: 2130706432(1.701412e+38), 0(0.000000e+00) -; CM-NEXT: SETGT_INT T6.X, T0.Y, literal.x, -; CM-NEXT: CNDE_INT T0.Y, T4.W, T2.X, PV.W, -; CM-NEXT: CNDE_INT * T1.Z, T2.Z, PV.Z, T1.Z, -; CM-NEXT: 127(1.779649e-43), 0(0.000000e+00) -; CM-NEXT: ALU clause starting at 205: -; CM-NEXT: LSHL * T2.W, T5.Y, literal.x, -; CM-NEXT: 23(3.222986e-44), 0(0.000000e+00) -; CM-NEXT: ADD_INT T2.X, PV.W, literal.x, -; CM-NEXT: CNDE_INT T0.Y, T1.Y, T1.Z, T0.Y, -; CM-NEXT: CNDE_INT * T1.Z, T6.X, T4.X, T1.X, +; CM-NEXT: SETGT_INT T8.X, T0.Z, literal.x, +; CM-NEXT: CNDE_INT T0.Y, T1.W, PV.W, T1.Y, +; CM-NEXT: CNDE_INT T0.Z, T4.Y, T7.X, PV.Z, +; CM-NEXT: LSHL * T0.W, PV.Y, literal.y, +; CM-NEXT: 127(1.779649e-43), 23(3.222986e-44) +; CM-NEXT: ALU clause starting at 202: +; CM-NEXT: ADD_INT T7.X, T0.W, literal.x, +; CM-NEXT: CNDE_INT * T0.Y, T5.X, T0.Y, T0.Z, ; CM-NEXT: 1065353216(1.000000e+00), 0(0.000000e+00) -; CM-NEXT: CNDE_INT * T1.W, T1.W, T3.Y, T2.Y, -; CM-NEXT: CNDE_INT T1.X, T0.Z, PV.W, T0.W, -; CM-NEXT: LSHL T1.Y, T1.Z, literal.x, BS:VEC_120/SCL_212 -; CM-NEXT: MUL_IEEE T0.Z, T0.Y, T2.X, +; CM-NEXT: CNDE_INT * T0.Z, T8.X, T0.X, T6.X, +; CM-NEXT: MUL_IEEE * T0.W, T4.X, literal.x, +; CM-NEXT: 2130706432(1.701412e+38), 0(0.000000e+00) +; CM-NEXT: CNDE_INT T0.X, T2.W, T4.X, PV.W, +; CM-NEXT: LSHL T1.Y, T0.Z, literal.x, +; CM-NEXT: MUL_IEEE T0.Z, T0.Y, T7.X, BS:VEC_021/SCL_122 ; CM-NEXT: SETGT * T0.W, literal.y, KC0[4].X, ; CM-NEXT: 23(3.222986e-44), -1036817932(-4.485347e+01) -; CM-NEXT: CNDE T2.X, PV.W, PV.Z, 0.0, +; CM-NEXT: CNDE T4.X, PV.W, PV.Z, 0.0, ; CM-NEXT: SETGT T0.Y, KC0[4].X, literal.x, ; CM-NEXT: ADD_INT T0.Z, PV.Y, literal.y, -; CM-NEXT: CNDE_INT * T0.W, T6.X, PV.X, T5.X, +; CM-NEXT: CNDE_INT * T0.W, T8.X, T3.X, PV.X, ; CM-NEXT: 1109008539(3.853184e+01), 1065353216(1.000000e+00) -; CM-NEXT: SETGT T1.X, KC0[3].W, literal.x, +; CM-NEXT: SETGT T0.X, KC0[3].W, literal.x, ; CM-NEXT: MUL_IEEE T1.Y, PV.W, PV.Z, ; CM-NEXT: SETGT T0.Z, literal.y, KC0[3].Z, ; CM-NEXT: CNDE * T0.W, PV.Y, PV.X, literal.z, ; CM-NEXT: 1109008539(3.853184e+01), -1036817932(-4.485347e+01) ; CM-NEXT: 2139095040(INF), 0(0.000000e+00) -; CM-NEXT: SETGT T2.X, literal.x, KC0[3].Y, +; CM-NEXT: SETGT T3.X, literal.x, KC0[3].Y, ; CM-NEXT: CNDE T0.Y, PV.Z, PV.Y, 0.0, -; CM-NEXT: CNDE T0.Z, PV.X, T3.X, literal.y, +; CM-NEXT: CNDE T0.Z, PV.X, T2.X, literal.y, ; CM-NEXT: SETGT * T1.W, KC0[3].Z, literal.z, ; CM-NEXT: -1036817932(-4.485347e+01), 2139095040(INF) ; CM-NEXT: 1109008539(3.853184e+01), 0(0.000000e+00) ; CM-NEXT: CNDE T0.Y, PV.W, PV.Y, literal.x, -; CM-NEXT: CNDE T1.Z, PV.X, T0.X, 0.0, +; CM-NEXT: CNDE T1.Z, PV.X, T1.X, 0.0, ; CM-NEXT: SETGT * T1.W, KC0[3].Y, literal.y, ; CM-NEXT: 2139095040(INF), 1109008539(3.853184e+01) ; CM-NEXT: CNDE * T0.X, PV.W, PV.Z, literal.x, diff --git a/llvm/test/CodeGen/AMDGPU/shl.ll b/llvm/test/CodeGen/AMDGPU/shl.ll index b1a82daa8e7d..b3f4790df4d4 100644 --- a/llvm/test/CodeGen/AMDGPU/shl.ll +++ b/llvm/test/CodeGen/AMDGPU/shl.ll @@ -795,17 +795,17 @@ define amdgpu_kernel void @shl_i64(ptr addrspace(1) %out, ptr addrspace(1) %in) ; EG-NEXT: ALU clause starting at 8: ; EG-NEXT: MOV * T0.X, KC0[2].Z, ; EG-NEXT: ALU clause starting at 9: -; EG-NEXT: AND_INT T1.Y, T0.Z, literal.x, -; EG-NEXT: LSHR T1.Z, T0.Y, 1, +; EG-NEXT: LSHR T1.Y, T0.Y, 1, +; EG-NEXT: NOT_INT T1.Z, T0.Z, ; EG-NEXT: BIT_ALIGN_INT T0.W, T0.Y, T0.X, 1, -; EG-NEXT: NOT_INT * T1.W, T0.Z, +; EG-NEXT: AND_INT * T1.W, T0.Z, literal.x, ; EG-NEXT: 31(4.344025e-44), 0(0.000000e+00) -; EG-NEXT: BIT_ALIGN_INT T1.Z, PV.Z, PV.W, PS, -; EG-NEXT: LSHL T0.W, T0.X, PV.Y, +; EG-NEXT: LSHL T2.Z, T0.X, PS, +; EG-NEXT: BIT_ALIGN_INT T0.W, PV.Y, PV.W, PV.Z, ; EG-NEXT: AND_INT * T1.W, T0.Z, literal.x, ; EG-NEXT: 32(4.484155e-44), 0(0.000000e+00) -; EG-NEXT: CNDE_INT * T0.Y, PS, PV.Z, PV.W, -; EG-NEXT: CNDE_INT T0.X, T1.W, T0.W, 0.0, +; EG-NEXT: CNDE_INT * T0.Y, PS, PV.W, PV.Z, +; EG-NEXT: CNDE_INT T0.X, T1.W, T2.Z, 0.0, ; EG-NEXT: LSHR * T1.X, KC0[2].Y, literal.x, ; EG-NEXT: 2(2.802597e-45), 0(0.000000e+00) %b_ptr = getelementptr i64, ptr addrspace(1) %in, i64 1 @@ -858,8 +858,8 @@ define amdgpu_kernel void @shl_v2i64(ptr addrspace(1) %out, ptr addrspace(1) %in ; EG: ; %bb.0: ; EG-NEXT: ALU 0, @10, KC0[CB0:0-32], KC1[] ; EG-NEXT: TEX 1 @6 -; EG-NEXT: ALU 22, @11, KC0[CB0:0-32], KC1[] -; EG-NEXT: MEM_RAT_CACHELESS STORE_RAW T3.XYZW, T0.X, 1 +; EG-NEXT: ALU 23, @11, KC0[CB0:0-32], KC1[] +; EG-NEXT: MEM_RAT_CACHELESS STORE_RAW T2.XYZW, T0.X, 1 ; EG-NEXT: CF_END ; EG-NEXT: PAD ; EG-NEXT: Fetch clause starting at 6: @@ -868,27 +868,28 @@ define amdgpu_kernel void @shl_v2i64(ptr addrspace(1) %out, ptr addrspace(1) %in ; EG-NEXT: ALU clause starting at 10: ; EG-NEXT: MOV * T0.X, KC0[2].Z, ; EG-NEXT: ALU clause starting at 11: -; EG-NEXT: AND_INT T1.Y, T1.Z, literal.x, +; EG-NEXT: AND_INT * T1.W, T1.Z, literal.x, +; EG-NEXT: 31(4.344025e-44), 0(0.000000e+00) +; EG-NEXT: LSHL T2.X, T0.Z, PV.W, +; EG-NEXT: AND_INT T1.Y, T1.Z, literal.x, BS:VEC_120/SCL_212 ; EG-NEXT: LSHR T2.Z, T0.W, 1, -; EG-NEXT: BIT_ALIGN_INT T0.W, T0.W, T0.Z, 1, +; EG-NEXT: BIT_ALIGN_INT T0.W, T0.W, T0.Z, 1, BS:VEC_102/SCL_221 ; EG-NEXT: NOT_INT * T1.W, T1.Z, +; EG-NEXT: 32(4.484155e-44), 0(0.000000e+00) +; EG-NEXT: BIT_ALIGN_INT T3.X, PV.Z, PV.W, PS, +; EG-NEXT: LSHR T2.Y, T0.Y, 1, +; EG-NEXT: NOT_INT T0.Z, T1.X, +; EG-NEXT: BIT_ALIGN_INT T0.W, T0.Y, T0.X, 1, +; EG-NEXT: AND_INT * T1.W, T1.X, literal.x, ; EG-NEXT: 31(4.344025e-44), 0(0.000000e+00) -; EG-NEXT: BIT_ALIGN_INT T0.W, PV.Z, PV.W, PS, -; EG-NEXT: LSHL * T1.W, T0.Z, PV.Y, -; EG-NEXT: AND_INT T2.X, T1.Z, literal.x, -; EG-NEXT: AND_INT T1.Y, T1.X, literal.y, -; EG-NEXT: LSHR T0.Z, T0.Y, 1, -; EG-NEXT: BIT_ALIGN_INT T2.W, T0.Y, T0.X, 1, -; EG-NEXT: NOT_INT * T3.W, T1.X, -; EG-NEXT: 32(4.484155e-44), 31(4.344025e-44) -; EG-NEXT: BIT_ALIGN_INT T0.Y, PV.Z, PV.W, PS, -; EG-NEXT: LSHL T0.Z, T0.X, PV.Y, -; EG-NEXT: AND_INT T2.W, T1.X, literal.x, BS:VEC_120/SCL_212 -; EG-NEXT: CNDE_INT * T3.W, PV.X, T0.W, T1.W, +; EG-NEXT: LSHL T0.Y, T0.X, PS, BS:VEC_120/SCL_212 +; EG-NEXT: AND_INT T1.Z, T1.X, literal.x, BS:VEC_201 +; EG-NEXT: BIT_ALIGN_INT T0.W, PV.Y, PV.W, PV.Z, +; EG-NEXT: CNDE_INT * T2.W, T1.Y, PV.X, T2.X, ; EG-NEXT: 32(4.484155e-44), 0(0.000000e+00) -; EG-NEXT: CNDE_INT T3.Y, PV.W, PV.Y, PV.Z, -; EG-NEXT: CNDE_INT * T3.Z, T2.X, T1.W, 0.0, -; EG-NEXT: CNDE_INT T3.X, T2.W, T0.Z, 0.0, +; EG-NEXT: CNDE_INT T2.Y, PV.Z, PV.W, PV.Y, +; EG-NEXT: CNDE_INT * T2.Z, T1.Y, T2.X, 0.0, +; EG-NEXT: CNDE_INT T2.X, T1.Z, T0.Y, 0.0, ; EG-NEXT: LSHR * T0.X, KC0[2].Y, literal.x, ; EG-NEXT: 2(2.802597e-45), 0(0.000000e+00) %b_ptr = getelementptr <2 x i64>, ptr addrspace(1) %in, i64 1 @@ -955,65 +956,66 @@ define amdgpu_kernel void @shl_v4i64(ptr addrspace(1) %out, ptr addrspace(1) %in ; EG: ; %bb.0: ; EG-NEXT: ALU 0, @14, KC0[CB0:0-32], KC1[] ; EG-NEXT: TEX 3 @6 -; EG-NEXT: ALU 47, @15, KC0[CB0:0-32], KC1[] -; EG-NEXT: MEM_RAT_CACHELESS STORE_RAW T1.XYZW, T2.X, 0 -; EG-NEXT: MEM_RAT_CACHELESS STORE_RAW T4.XYZW, T0.X, 1 +; EG-NEXT: ALU 48, @15, KC0[CB0:0-32], KC1[] +; EG-NEXT: MEM_RAT_CACHELESS STORE_RAW T2.XYZW, T0.X, 0 +; EG-NEXT: MEM_RAT_CACHELESS STORE_RAW T3.XYZW, T1.X, 1 ; EG-NEXT: CF_END ; EG-NEXT: Fetch clause starting at 6: -; EG-NEXT: VTX_READ_128 T1.XYZW, T0.X, 48, #1 -; EG-NEXT: VTX_READ_128 T2.XYZW, T0.X, 0, #1 -; EG-NEXT: VTX_READ_128 T3.XYZW, T0.X, 32, #1 -; EG-NEXT: VTX_READ_128 T0.XYZW, T0.X, 16, #1 +; EG-NEXT: VTX_READ_128 T1.XYZW, T0.X, 32, #1 +; EG-NEXT: VTX_READ_128 T2.XYZW, T0.X, 48, #1 +; EG-NEXT: VTX_READ_128 T3.XYZW, T0.X, 16, #1 +; EG-NEXT: VTX_READ_128 T0.XYZW, T0.X, 0, #1 ; EG-NEXT: ALU clause starting at 14: ; EG-NEXT: MOV * T0.X, KC0[2].Z, ; EG-NEXT: ALU clause starting at 15: -; EG-NEXT: AND_INT T4.Z, T1.Z, literal.x, -; EG-NEXT: LSHR T1.W, T0.W, 1, -; EG-NEXT: NOT_INT * T3.W, T1.Z, +; EG-NEXT: AND_INT * T1.W, T1.Z, literal.x, ; EG-NEXT: 31(4.344025e-44), 0(0.000000e+00) -; EG-NEXT: BIT_ALIGN_INT T4.X, T0.W, T0.Z, 1, -; EG-NEXT: AND_INT T1.Y, T3.Z, literal.x, BS:VEC_201 -; EG-NEXT: LSHR T5.Z, T2.W, 1, BS:VEC_120/SCL_212 -; EG-NEXT: BIT_ALIGN_INT T0.W, T2.W, T2.Z, 1, BS:VEC_102/SCL_221 -; EG-NEXT: NOT_INT * T2.W, T3.Z, -; EG-NEXT: 31(4.344025e-44), 0(0.000000e+00) -; EG-NEXT: BIT_ALIGN_INT T3.Y, PV.Z, PV.W, PS, -; EG-NEXT: LSHL T2.Z, T2.Z, PV.Y, -; EG-NEXT: BIT_ALIGN_INT T0.W, T1.W, PV.X, T3.W, -; EG-NEXT: LSHL * T1.W, T0.Z, T4.Z, +; EG-NEXT: LSHL * T1.W, T0.Z, PV.W, ; EG-NEXT: AND_INT T4.X, T1.Z, literal.x, -; EG-NEXT: AND_INT T1.Y, T1.X, literal.y, -; EG-NEXT: LSHR T0.Z, T0.Y, 1, -; EG-NEXT: BIT_ALIGN_INT T2.W, T0.Y, T0.X, 1, -; EG-NEXT: NOT_INT * T3.W, T1.X, +; EG-NEXT: LSHR T1.Y, T3.W, 1, +; EG-NEXT: NOT_INT T4.Z, T2.Z, BS:VEC_201 +; EG-NEXT: BIT_ALIGN_INT T2.W, T3.W, T3.Z, 1, +; EG-NEXT: AND_INT * T3.W, T2.Z, literal.y, ; EG-NEXT: 32(4.484155e-44), 31(4.344025e-44) -; EG-NEXT: AND_INT T5.X, T3.Z, literal.x, -; EG-NEXT: BIT_ALIGN_INT T0.Y, PV.Z, PV.W, PS, -; EG-NEXT: LSHL T0.Z, T0.X, PV.Y, -; EG-NEXT: AND_INT T2.W, T1.X, literal.x, BS:VEC_120/SCL_212 -; EG-NEXT: CNDE_INT * T4.W, PV.X, T0.W, T1.W, +; EG-NEXT: LSHL T5.X, T3.Z, PS, +; EG-NEXT: AND_INT T2.Y, T2.Z, literal.x, BS:VEC_120/SCL_212 +; EG-NEXT: BIT_ALIGN_INT T2.Z, PV.Y, PV.W, PV.Z, +; EG-NEXT: LSHR T2.W, T3.Y, 1, +; EG-NEXT: NOT_INT * T3.W, T2.X, +; EG-NEXT: 32(4.484155e-44), 0(0.000000e+00) +; EG-NEXT: BIT_ALIGN_INT T6.X, T3.Y, T3.X, 1, +; EG-NEXT: AND_INT T1.Y, T2.X, literal.x, +; EG-NEXT: LSHR T3.Z, T0.W, 1, +; EG-NEXT: BIT_ALIGN_INT T0.W, T0.W, T0.Z, 1, +; EG-NEXT: NOT_INT * T4.W, T1.Z, +; EG-NEXT: 31(4.344025e-44), 0(0.000000e+00) +; EG-NEXT: BIT_ALIGN_INT T7.X, PV.Z, PV.W, PS, +; EG-NEXT: LSHL T1.Y, T3.X, PV.Y, BS:VEC_120/SCL_212 +; EG-NEXT: AND_INT T0.Z, T2.X, literal.x, BS:VEC_201 +; EG-NEXT: BIT_ALIGN_INT T0.W, T2.W, PV.X, T3.W, +; EG-NEXT: CNDE_INT * T3.W, T2.Y, T2.Z, T5.X, ; EG-NEXT: 32(4.484155e-44), 0(0.000000e+00) -; EG-NEXT: AND_INT T0.X, T3.X, literal.x, -; EG-NEXT: CNDE_INT T4.Y, PV.W, PV.Y, PV.Z, -; EG-NEXT: LSHR T1.Z, T2.Y, 1, -; EG-NEXT: BIT_ALIGN_INT T0.W, T2.Y, T2.X, 1, -; EG-NEXT: NOT_INT * T3.W, T3.X, +; EG-NEXT: LSHR T2.X, T0.Y, 1, +; EG-NEXT: CNDE_INT T3.Y, PV.Z, PV.W, PV.Y, +; EG-NEXT: NOT_INT T1.Z, T1.X, +; EG-NEXT: BIT_ALIGN_INT T0.W, T0.Y, T0.X, 1, +; EG-NEXT: AND_INT * T2.W, T1.X, literal.x, ; EG-NEXT: 31(4.344025e-44), 0(0.000000e+00) -; EG-NEXT: BIT_ALIGN_INT T1.X, PV.Z, PV.W, PS, -; EG-NEXT: LSHL T0.Y, T2.X, PV.X, -; EG-NEXT: CNDE_INT T4.Z, T4.X, T1.W, 0.0, BS:VEC_120/SCL_212 -; EG-NEXT: AND_INT * T0.W, T3.X, literal.x, BS:VEC_201 +; EG-NEXT: LSHL T0.X, T0.X, PS, +; EG-NEXT: AND_INT T0.Y, T1.X, literal.x, BS:VEC_120/SCL_212 +; EG-NEXT: CNDE_INT T3.Z, T2.Y, T5.X, 0.0, BS:VEC_021/SCL_122 +; EG-NEXT: BIT_ALIGN_INT * T0.W, PV.X, PV.W, PV.Z, ; EG-NEXT: 32(4.484155e-44), 0(0.000000e+00) -; EG-NEXT: CNDE_INT * T1.W, T5.X, T3.Y, T2.Z, -; EG-NEXT: CNDE_INT T4.X, T2.W, T0.Z, 0.0, -; EG-NEXT: CNDE_INT T1.Y, T0.W, T1.X, T0.Y, BS:VEC_120/SCL_212 -; EG-NEXT: ADD_INT * T2.W, KC0[2].Y, literal.x, +; EG-NEXT: CNDE_INT * T2.W, T4.X, T7.X, T1.W, +; EG-NEXT: CNDE_INT T3.X, T0.Z, T1.Y, 0.0, +; EG-NEXT: CNDE_INT T2.Y, T0.Y, T0.W, T0.X, +; EG-NEXT: ADD_INT * T0.W, KC0[2].Y, literal.x, ; EG-NEXT: 16(2.242078e-44), 0(0.000000e+00) -; EG-NEXT: LSHR T0.X, PV.W, literal.x, -; EG-NEXT: CNDE_INT T1.Z, T5.X, T2.Z, 0.0, -; EG-NEXT: CNDE_INT * T1.X, T0.W, T0.Y, 0.0, +; EG-NEXT: LSHR T1.X, PV.W, literal.x, +; EG-NEXT: CNDE_INT T2.Z, T4.X, T1.W, 0.0, +; EG-NEXT: CNDE_INT * T2.X, T0.Y, T0.X, 0.0, ; EG-NEXT: 2(2.802597e-45), 0(0.000000e+00) -; EG-NEXT: LSHR * T2.X, KC0[2].Y, literal.x, +; EG-NEXT: LSHR * T0.X, KC0[2].Y, literal.x, ; EG-NEXT: 2(2.802597e-45), 0(0.000000e+00) %b_ptr = getelementptr <4 x i64>, ptr addrspace(1) %in, i64 1 %a = load <4 x i64>, ptr addrspace(1) %in @@ -1172,17 +1174,17 @@ define amdgpu_kernel void @s_shl_constant_i64(ptr addrspace(1) %out, i64 %a) { ; EG-NEXT: CF_END ; EG-NEXT: PAD ; EG-NEXT: ALU clause starting at 4: -; EG-NEXT: AND_INT T0.Z, KC0[2].W, literal.x, -; EG-NEXT: MOV T0.W, literal.y, -; EG-NEXT: NOT_INT * T1.W, KC0[2].W, -; EG-NEXT: 31(4.344025e-44), -1(nan) -; EG-NEXT: BIT_ALIGN_INT T1.Z, literal.x, PV.W, PS, -; EG-NEXT: LSHL T0.W, literal.y, PV.Z, +; EG-NEXT: MOV T0.Z, literal.x, +; EG-NEXT: NOT_INT T0.W, KC0[2].W, +; EG-NEXT: AND_INT * T1.W, KC0[2].W, literal.y, +; EG-NEXT: -1(nan), 31(4.344025e-44) +; EG-NEXT: LSHL T1.Z, literal.x, PS, +; EG-NEXT: BIT_ALIGN_INT T0.W, literal.y, PV.Z, PV.W, ; EG-NEXT: AND_INT * T1.W, KC0[2].W, literal.z, -; EG-NEXT: 32767(4.591635e-41), -1(nan) +; EG-NEXT: -1(nan), 32767(4.591635e-41) ; EG-NEXT: 32(4.484155e-44), 0(0.000000e+00) -; EG-NEXT: CNDE_INT * T0.Y, PS, PV.Z, PV.W, -; EG-NEXT: CNDE_INT T0.X, T1.W, T0.W, 0.0, +; EG-NEXT: CNDE_INT * T0.Y, PS, PV.W, PV.Z, +; EG-NEXT: CNDE_INT T0.X, T1.W, T1.Z, 0.0, ; EG-NEXT: LSHR * T1.X, KC0[2].Y, literal.x, ; EG-NEXT: 2(2.802597e-45), 0(0.000000e+00) %shl = shl i64 281474976710655, %a @@ -1423,15 +1425,15 @@ define amdgpu_kernel void @s_shl_inline_imm_64_i64(ptr addrspace(1) %out, ptr ad ; EG-NEXT: CF_END ; EG-NEXT: PAD ; EG-NEXT: ALU clause starting at 4: -; EG-NEXT: NOT_INT T0.W, KC0[2].W, -; EG-NEXT: AND_INT * T1.W, KC0[2].W, literal.x, +; EG-NEXT: AND_INT T0.W, KC0[2].W, literal.x, +; EG-NEXT: NOT_INT * T1.W, KC0[2].W, ; EG-NEXT: 31(4.344025e-44), 0(0.000000e+00) -; EG-NEXT: LSHL T0.Z, literal.x, PS, -; EG-NEXT: BIT_ALIGN_INT T0.W, 0.0, literal.y, PV.W, -; EG-NEXT: AND_INT * T1.W, KC0[2].W, literal.y, -; EG-NEXT: 64(8.968310e-44), 32(4.484155e-44) -; EG-NEXT: CNDE_INT * T0.Y, PS, PV.W, PV.Z, -; EG-NEXT: CNDE_INT T0.X, T1.W, T0.Z, 0.0, +; EG-NEXT: BIT_ALIGN_INT T0.Z, 0.0, literal.x, PS, +; EG-NEXT: AND_INT T1.W, KC0[2].W, literal.x, +; EG-NEXT: LSHL * T0.W, literal.y, PV.W, +; EG-NEXT: 32(4.484155e-44), 64(8.968310e-44) +; EG-NEXT: CNDE_INT * T0.Y, PV.W, PV.Z, PS, +; EG-NEXT: CNDE_INT T0.X, T1.W, T0.W, 0.0, ; EG-NEXT: LSHR * T1.X, KC0[2].Y, literal.x, ; EG-NEXT: 2(2.802597e-45), 0(0.000000e+00) %shl = shl i64 64, %a @@ -1903,16 +1905,16 @@ define amdgpu_kernel void @s_shl_inline_imm_f32_4_0_i64(ptr addrspace(1) %out, p ; EG-NEXT: CF_END ; EG-NEXT: PAD ; EG-NEXT: ALU clause starting at 4: -; EG-NEXT: NOT_INT T0.W, KC0[2].W, -; EG-NEXT: AND_INT * T1.W, KC0[2].W, literal.x, +; EG-NEXT: AND_INT T0.W, KC0[2].W, literal.x, +; EG-NEXT: NOT_INT * T1.W, KC0[2].W, ; EG-NEXT: 31(4.344025e-44), 0(0.000000e+00) -; EG-NEXT: LSHL T0.Z, literal.x, PS, -; EG-NEXT: BIT_ALIGN_INT T0.W, 0.0, literal.y, PV.W, -; EG-NEXT: AND_INT * T1.W, KC0[2].W, literal.z, -; EG-NEXT: 1082130432(4.000000e+00), 541065216(1.626303e-19) -; EG-NEXT: 32(4.484155e-44), 0(0.000000e+00) -; EG-NEXT: CNDE_INT * T0.Y, PS, PV.W, PV.Z, -; EG-NEXT: CNDE_INT T0.X, T1.W, T0.Z, 0.0, +; EG-NEXT: BIT_ALIGN_INT T0.Z, 0.0, literal.x, PS, +; EG-NEXT: AND_INT T1.W, KC0[2].W, literal.y, +; EG-NEXT: LSHL * T0.W, literal.z, PV.W, +; EG-NEXT: 541065216(1.626303e-19), 32(4.484155e-44) +; EG-NEXT: 1082130432(4.000000e+00), 0(0.000000e+00) +; EG-NEXT: CNDE_INT * T0.Y, PV.W, PV.Z, PS, +; EG-NEXT: CNDE_INT T0.X, T1.W, T0.W, 0.0, ; EG-NEXT: LSHR * T1.X, KC0[2].Y, literal.x, ; EG-NEXT: 2(2.802597e-45), 0(0.000000e+00) %shl = shl i64 1082130432, %a @@ -1959,17 +1961,17 @@ define amdgpu_kernel void @s_shl_inline_imm_f32_neg_4_0_i64(ptr addrspace(1) %ou ; EG-NEXT: CF_END ; EG-NEXT: PAD ; EG-NEXT: ALU clause starting at 4: -; EG-NEXT: AND_INT T0.Z, KC0[2].W, literal.x, -; EG-NEXT: MOV T0.W, literal.y, -; EG-NEXT: NOT_INT * T1.W, KC0[2].W, -; EG-NEXT: 31(4.344025e-44), -532676608(-5.534023e+19) -; EG-NEXT: BIT_ALIGN_INT T1.Z, literal.x, PV.W, PS, -; EG-NEXT: LSHL T0.W, literal.y, PV.Z, +; EG-NEXT: MOV T0.Z, literal.x, +; EG-NEXT: NOT_INT T0.W, KC0[2].W, +; EG-NEXT: AND_INT * T1.W, KC0[2].W, literal.y, +; EG-NEXT: -532676608(-5.534023e+19), 31(4.344025e-44) +; EG-NEXT: LSHL T1.Z, literal.x, PS, +; EG-NEXT: BIT_ALIGN_INT T0.W, literal.y, PV.Z, PV.W, ; EG-NEXT: AND_INT * T1.W, KC0[2].W, literal.z, -; EG-NEXT: 2147483647(nan), -1065353216(-4.000000e+00) +; EG-NEXT: -1065353216(-4.000000e+00), 2147483647(nan) ; EG-NEXT: 32(4.484155e-44), 0(0.000000e+00) -; EG-NEXT: CNDE_INT * T0.Y, PS, PV.Z, PV.W, -; EG-NEXT: CNDE_INT T0.X, T1.W, T0.W, 0.0, +; EG-NEXT: CNDE_INT * T0.Y, PS, PV.W, PV.Z, +; EG-NEXT: CNDE_INT T0.X, T1.W, T1.Z, 0.0, ; EG-NEXT: LSHR * T1.X, KC0[2].Y, literal.x, ; EG-NEXT: 2(2.802597e-45), 0(0.000000e+00) %shl = shl i64 -1065353216, %a -- GitLab From c609c04e32ef43f63a6ee54025fadf649c3247cc Mon Sep 17 00:00:00 2001 From: Nikita Popov Date: Wed, 22 May 2024 08:37:09 +0200 Subject: [PATCH 074/452] [CodeGen] Use fixed triple in weak-external test (NFC) The codegen here differs substantially if UseARMMethodPtrABI is enabled. Use a fixed x86 triple to avoid this. --- clang/test/CodeGenCXX/weak-external.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clang/test/CodeGenCXX/weak-external.cpp b/clang/test/CodeGenCXX/weak-external.cpp index 587fba36a0ad..02f05bfa7e1e 100644 --- a/clang/test/CodeGenCXX/weak-external.cpp +++ b/clang/test/CodeGenCXX/weak-external.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -fcxx-exceptions -fexceptions -triple %itanium_abi_triple %s -emit-llvm -o - | FileCheck %s +// RUN: %clang_cc1 -fcxx-exceptions -fexceptions -triple x86_64-unknown-linux-gnu %s -emit-llvm -o - | FileCheck %s // PR4262 // CHECK-NOT: _ZNSs12_S_constructIPKcEEPcT_S3_RKSaIcESt20forward_iterator_tag -- GitLab From 874a5dab419240af0a02a3fc70accd926105aa31 Mon Sep 17 00:00:00 2001 From: Ivan Murashko Date: Wed, 22 May 2024 07:47:10 +0100 Subject: [PATCH 075/452] [clang] Processing real directories added as virtual ones (#91645) The `FileManager` might create a virtual directory that can be used later as a search path. This is the case when we use remapping, as demonstrated in the suggested LIT test. We might encounter a 'false cache miss' and add the same directory twice into `FileManager::SeenDirEntries` if the added record is a real directory that is present on a disk: - Once as a virtual directory - And once as a real one This isn't a problem if the added directories have the same name, as in this case, we will get a cache hit. However, it could lead to compilation errors if the directory names are different but point to the same folder. For example, one might use an absolute name and another a relative one. For instance, the **implicit-module-remap.cpp** LIT test will fail with the following message: ``` /.../implicit-module-remap.cpp.tmp/test.cpp:1:2: fatal error: module 'a' was built in directory '/.../implicit-module-remap.cpp.tmp' but now resides in directory '.' 1 | #include "a.h" | ^ 1 error generated. ``` The suggested fix checks if the added virtual directory is present on the disk and handles it as a real one if that is the case. --- clang/include/clang/Basic/FileManager.h | 2 + clang/lib/Basic/FileManager.cpp | 48 ++++++++++++++------ clang/test/Modules/implicit-module-remap.cpp | 21 +++++++++ 3 files changed, 56 insertions(+), 15 deletions(-) create mode 100644 clang/test/Modules/implicit-module-remap.cpp diff --git a/clang/include/clang/Basic/FileManager.h b/clang/include/clang/Basic/FileManager.h index 8b4206e52cd4..e1f33d57a898 100644 --- a/clang/include/clang/Basic/FileManager.h +++ b/clang/include/clang/Basic/FileManager.h @@ -299,6 +299,8 @@ private: getBufferForFileImpl(StringRef Filename, int64_t FileSize, bool isVolatile, bool RequiresNullTerminator) const; + DirectoryEntry *&getRealDirEntry(const llvm::vfs::Status &Status); + public: /// Get the 'stat' information for the given \p Path. /// diff --git a/clang/lib/Basic/FileManager.cpp b/clang/lib/Basic/FileManager.cpp index 143c04309d07..1dc51deb8298 100644 --- a/clang/lib/Basic/FileManager.cpp +++ b/clang/lib/Basic/FileManager.cpp @@ -82,6 +82,22 @@ getDirectoryFromFile(FileManager &FileMgr, StringRef Filename, return FileMgr.getDirectoryRef(DirName, CacheFailure); } +DirectoryEntry *&FileManager::getRealDirEntry(const llvm::vfs::Status &Status) { + assert(Status.isDirectory() && "The directory should exist!"); + // See if we have already opened a directory with the + // same inode (this occurs on Unix-like systems when one dir is + // symlinked to another, for example) or the same path (on + // Windows). + DirectoryEntry *&UDE = UniqueRealDirs[Status.getUniqueID()]; + + if (!UDE) { + // We don't have this directory yet, add it. We use the string + // key from the SeenDirEntries map as the string. + UDE = new (DirsAlloc.Allocate()) DirectoryEntry(); + } + return UDE; +} + /// Add all ancestors of the given path (pointing to either a file or /// a directory) as virtual directories. void FileManager::addAncestorsAsVirtualDirs(StringRef Path) { @@ -99,10 +115,21 @@ void FileManager::addAncestorsAsVirtualDirs(StringRef Path) { if (NamedDirEnt.second) return; - // Add the virtual directory to the cache. - auto *UDE = new (DirsAlloc.Allocate()) DirectoryEntry(); - NamedDirEnt.second = *UDE; - VirtualDirectoryEntries.push_back(UDE); + // Check to see if the directory exists. + llvm::vfs::Status Status; + auto statError = + getStatValue(DirName, Status, false, nullptr /*directory lookup*/); + if (statError) { + // There's no real directory at the given path. + // Add the virtual directory to the cache. + auto *UDE = new (DirsAlloc.Allocate()) DirectoryEntry(); + NamedDirEnt.second = *UDE; + VirtualDirectoryEntries.push_back(UDE); + } else { + // There is the real directory + DirectoryEntry *&UDE = getRealDirEntry(Status); + NamedDirEnt.second = *UDE; + } // Recursively add the other ancestors. addAncestorsAsVirtualDirs(DirName); @@ -162,17 +189,8 @@ FileManager::getDirectoryRef(StringRef DirName, bool CacheFailure) { return llvm::errorCodeToError(statError); } - // It exists. See if we have already opened a directory with the - // same inode (this occurs on Unix-like systems when one dir is - // symlinked to another, for example) or the same path (on - // Windows). - DirectoryEntry *&UDE = UniqueRealDirs[Status.getUniqueID()]; - - if (!UDE) { - // We don't have this directory yet, add it. We use the string - // key from the SeenDirEntries map as the string. - UDE = new (DirsAlloc.Allocate()) DirectoryEntry(); - } + // It exists. + DirectoryEntry *&UDE = getRealDirEntry(Status); NamedDirEnt.second = *UDE; return DirectoryEntryRef(NamedDirEnt); diff --git a/clang/test/Modules/implicit-module-remap.cpp b/clang/test/Modules/implicit-module-remap.cpp new file mode 100644 index 000000000000..47927b969401 --- /dev/null +++ b/clang/test/Modules/implicit-module-remap.cpp @@ -0,0 +1,21 @@ +// RUN: rm -rf %t +// RUN: split-file %s %t +// RUN: cd %t +// +// RUN: %clang_cc1 -fmodules -fmodule-map-file=module.modulemap -fmodules-cache-path=%t -remap-file "test.cpp;%t/test.cpp" %t/test.cpp + +//--- a.h +#define FOO + +//--- module.modulemap +module a { + header "a.h" +} + +//--- test.cpp +#include "a.h" + +#ifndef FOO +#error foo +#endif + -- GitLab From b00e0c167186d69e1e6bceda57c09b272bd6acfc Mon Sep 17 00:00:00 2001 From: Christian Ulmann Date: Wed, 22 May 2024 08:48:10 +0200 Subject: [PATCH 076/452] [MLIR][Analysis] Consolidate topological sort utilities (#92563) This PR attempts to consolidate the different topological sort utilities into one place. It adds them to the analysis folder because the `SliceAnalysis` uses some of these. There are now two different sorting strategies: 1. Sort only according to SSA use-def chains 2. Sort while taking regions into account. This requires a much more elaborate traversal and cannot be applied on graph regions that easily. This additionally reimplements the region aware topological sorting because the previous implementation had an exponential space complexity. I'm open to suggestions on how to combine this further or how to fuse the test passes. --- mlir/include/mlir/Analysis/SliceAnalysis.h | 5 - .../TopologicalSortUtils.h | 14 +- mlir/include/mlir/Transforms/RegionUtils.h | 4 - mlir/lib/Analysis/CMakeLists.txt | 2 + mlir/lib/Analysis/SliceAnalysis.cpp | 59 +------ .../TopologicalSortUtils.cpp | 141 ++++++++++++++- .../Conversion/VectorToGPU/VectorToGPU.cpp | 1 + .../Dialect/Affine/Utils/LoopFusionUtils.cpp | 1 + .../ArmSME/Transforms/TileAllocation.cpp | 1 + .../OpenACC/OpenACCToLLVMIRTranslation.cpp | 2 +- .../OpenMP/OpenMPToLLVMIRTranslation.cpp | 1 + mlir/lib/Target/LLVMIR/ModuleTranslation.cpp | 2 +- mlir/lib/Transforms/Mem2Reg.cpp | 2 +- mlir/lib/Transforms/SROA.cpp | 1 + mlir/lib/Transforms/TopologicalSort.cpp | 2 +- mlir/lib/Transforms/Utils/CMakeLists.txt | 1 - mlir/lib/Transforms/Utils/RegionUtils.cpp | 19 +-- mlir/lib/Transforms/ViewOpGraph.cpp | 2 +- mlir/test/Analysis/test-topoligical-sort.mlir | 53 ++++-- .../test-toposort.mlir | 0 mlir/test/Dialect/Affine/slicing-utils.mlir | 160 +++++++++--------- mlir/test/lib/Analysis/CMakeLists.txt | 1 + mlir/test/lib/Analysis/TestSlice.cpp | 33 ++-- .../TestTopologicalSort.cpp | 2 +- mlir/test/lib/Transforms/CMakeLists.txt | 1 - .../llvm-project-overlay/mlir/BUILD.bazel | 1 - 26 files changed, 298 insertions(+), 213 deletions(-) rename mlir/include/mlir/{Transforms => Analysis}/TopologicalSortUtils.h (86%) rename mlir/lib/{Transforms/Utils => Analysis}/TopologicalSortUtils.cpp (50%) rename mlir/test/{Transforms => Analysis}/test-toposort.mlir (100%) rename mlir/test/lib/{Transforms => Analysis}/TestTopologicalSort.cpp (98%) diff --git a/mlir/include/mlir/Analysis/SliceAnalysis.h b/mlir/include/mlir/Analysis/SliceAnalysis.h index d5cdf72c3889..99279fdfe427 100644 --- a/mlir/include/mlir/Analysis/SliceAnalysis.h +++ b/mlir/include/mlir/Analysis/SliceAnalysis.h @@ -223,11 +223,6 @@ SetVector getSlice(Operation *op, const BackwardSliceOptions &backwardSliceOptions = {}, const ForwardSliceOptions &forwardSliceOptions = {}); -/// Multi-root DAG topological sort. -/// Performs a topological sort of the Operation in the `toSort` SetVector. -/// Returns a topologically sorted SetVector. -SetVector topologicalSort(const SetVector &toSort); - /// Utility to match a generic reduction given a list of iteration-carried /// arguments, `iterCarriedArgs` and the position of the potential reduction /// argument within the list, `redPos`. If a reduction is matched, returns the diff --git a/mlir/include/mlir/Transforms/TopologicalSortUtils.h b/mlir/include/mlir/Analysis/TopologicalSortUtils.h similarity index 86% rename from mlir/include/mlir/Transforms/TopologicalSortUtils.h rename to mlir/include/mlir/Analysis/TopologicalSortUtils.h index 74e44b1dc485..ee98cd8cb380 100644 --- a/mlir/include/mlir/Transforms/TopologicalSortUtils.h +++ b/mlir/include/mlir/Analysis/TopologicalSortUtils.h @@ -6,8 +6,8 @@ // //===----------------------------------------------------------------------===// -#ifndef MLIR_TRANSFORMS_TOPOLOGICALSORTUTILS_H -#define MLIR_TRANSFORMS_TOPOLOGICALSORTUTILS_H +#ifndef MLIR_ANALYSIS_TOPOLOGICALSORTUTILS_H +#define MLIR_ANALYSIS_TOPOLOGICALSORTUTILS_H #include "mlir/IR/Block.h" @@ -104,6 +104,14 @@ bool computeTopologicalSorting( MutableArrayRef ops, function_ref isOperandReady = nullptr); +/// Gets a list of blocks that is sorted according to dominance. This sort is +/// stable. +SetVector getBlocksSortedByDominance(Region ®ion); + +/// Sorts all operations in `toSort` topologically while also considering region +/// semantics. Does not support multi-sets. +SetVector topologicalSort(const SetVector &toSort); + } // end namespace mlir -#endif // MLIR_TRANSFORMS_TOPOLOGICALSORTUTILS_H +#endif // MLIR_ANALYSIS_TOPOLOGICALSORTUTILS_H diff --git a/mlir/include/mlir/Transforms/RegionUtils.h b/mlir/include/mlir/Transforms/RegionUtils.h index f65d0d44eef4..06eebff201d1 100644 --- a/mlir/include/mlir/Transforms/RegionUtils.h +++ b/mlir/include/mlir/Transforms/RegionUtils.h @@ -87,10 +87,6 @@ LogicalResult eraseUnreachableBlocks(RewriterBase &rewriter, LogicalResult runRegionDCE(RewriterBase &rewriter, MutableArrayRef regions); -/// Get a list of blocks that is sorted according to dominance. This sort is -/// stable. -SetVector getBlocksSortedByDominance(Region ®ion); - } // namespace mlir #endif // MLIR_TRANSFORMS_REGIONUTILS_H_ diff --git a/mlir/lib/Analysis/CMakeLists.txt b/mlir/lib/Analysis/CMakeLists.txt index 005814ddbec7..38d8415d81c7 100644 --- a/mlir/lib/Analysis/CMakeLists.txt +++ b/mlir/lib/Analysis/CMakeLists.txt @@ -6,6 +6,7 @@ set(LLVM_OPTIONAL_SOURCES Liveness.cpp CFGLoopInfo.cpp SliceAnalysis.cpp + TopologicalSortUtils.cpp AliasAnalysis/LocalAliasAnalysis.cpp @@ -28,6 +29,7 @@ add_mlir_library(MLIRAnalysis Liveness.cpp CFGLoopInfo.cpp SliceAnalysis.cpp + TopologicalSortUtils.cpp AliasAnalysis/LocalAliasAnalysis.cpp diff --git a/mlir/lib/Analysis/SliceAnalysis.cpp b/mlir/lib/Analysis/SliceAnalysis.cpp index 26fe8e3dc081..2b1cf411ceee 100644 --- a/mlir/lib/Analysis/SliceAnalysis.cpp +++ b/mlir/lib/Analysis/SliceAnalysis.cpp @@ -11,7 +11,8 @@ //===----------------------------------------------------------------------===// #include "mlir/Analysis/SliceAnalysis.h" -#include "mlir/IR/BuiltinOps.h" +#include "mlir/Analysis/TopologicalSortUtils.h" +#include "mlir/IR/Block.h" #include "mlir/IR/Operation.h" #include "mlir/Interfaces/SideEffectInterfaces.h" #include "mlir/Support/LLVM.h" @@ -164,62 +165,6 @@ mlir::getSlice(Operation *op, const BackwardSliceOptions &backwardSliceOptions, return topologicalSort(slice); } -namespace { -/// DFS post-order implementation that maintains a global count to work across -/// multiple invocations, to help implement topological sort on multi-root DAGs. -/// We traverse all operations but only record the ones that appear in -/// `toSort` for the final result. -struct DFSState { - DFSState(const SetVector &set) : toSort(set), seen() {} - const SetVector &toSort; - SmallVector topologicalCounts; - DenseSet seen; -}; -} // namespace - -static void dfsPostorder(Operation *root, DFSState *state) { - SmallVector queue(1, root); - std::vector ops; - while (!queue.empty()) { - Operation *current = queue.pop_back_val(); - ops.push_back(current); - for (Operation *op : current->getUsers()) - queue.push_back(op); - for (Region ®ion : current->getRegions()) { - for (Operation &op : region.getOps()) - queue.push_back(&op); - } - } - - for (Operation *op : llvm::reverse(ops)) { - if (state->seen.insert(op).second && state->toSort.count(op) > 0) - state->topologicalCounts.push_back(op); - } -} - -SetVector -mlir::topologicalSort(const SetVector &toSort) { - if (toSort.empty()) { - return toSort; - } - - // Run from each root with global count and `seen` set. - DFSState state(toSort); - for (auto *s : toSort) { - assert(toSort.count(s) == 1 && "NYI: multi-sets not supported"); - dfsPostorder(s, &state); - } - - // Reorder and return. - SetVector res; - for (auto it = state.topologicalCounts.rbegin(), - eit = state.topologicalCounts.rend(); - it != eit; ++it) { - res.insert(*it); - } - return res; -} - /// Returns true if `value` (transitively) depends on iteration-carried values /// of the given `ancestorOp`. static bool dependsOnCarriedVals(Value value, diff --git a/mlir/lib/Transforms/Utils/TopologicalSortUtils.cpp b/mlir/lib/Analysis/TopologicalSortUtils.cpp similarity index 50% rename from mlir/lib/Transforms/Utils/TopologicalSortUtils.cpp rename to mlir/lib/Analysis/TopologicalSortUtils.cpp index f3a9d217f2c9..c406960fdecc 100644 --- a/mlir/lib/Transforms/Utils/TopologicalSortUtils.cpp +++ b/mlir/lib/Analysis/TopologicalSortUtils.cpp @@ -1,4 +1,4 @@ -//===- TopologicalSortUtils.h - Topological sort utilities ------*- C++ -*-===// +//===- TopologicalSortUtils.cpp - Topological sort utilities --------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. @@ -6,8 +6,13 @@ // //===----------------------------------------------------------------------===// -#include "mlir/Transforms/TopologicalSortUtils.h" +#include "mlir/Analysis/TopologicalSortUtils.h" +#include "mlir/IR/Block.h" #include "mlir/IR/OpDefinition.h" +#include "mlir/IR/RegionGraphTraits.h" + +#include "llvm/ADT/PostOrderIterator.h" +#include "llvm/ADT/SetVector.h" using namespace mlir; @@ -146,3 +151,135 @@ bool mlir::computeTopologicalSorting( return allOpsScheduled; } + +SetVector mlir::getBlocksSortedByDominance(Region ®ion) { + // For each block that has not been visited yet (i.e. that has no + // predecessors), add it to the list as well as its successors. + SetVector blocks; + for (Block &b : region) { + if (blocks.count(&b) == 0) { + llvm::ReversePostOrderTraversal traversal(&b); + blocks.insert(traversal.begin(), traversal.end()); + } + } + assert(blocks.size() == region.getBlocks().size() && + "some blocks are not sorted"); + + return blocks; +} + +namespace { +class TopoSortHelper { +public: + explicit TopoSortHelper(const SetVector &toSort) + : toSort(toSort) {} + + /// Executes the topological sort of the operations this instance was + /// constructed with. This function will destroy the internal state of the + /// instance. + SetVector sort() { + if (toSort.size() <= 1) { + // Note: Creates a copy on purpose. + return toSort; + } + + // First, find the root region to start the traversal through the IR. This + // additionally enriches the internal caches with all relevant ancestor + // regions and blocks. + Region *rootRegion = findCommonAncestorRegion(); + assert(rootRegion && "expected all ops to have a common ancestor"); + + // Sort all elements in `toSort` by traversing the IR in the appropriate + // order. + SetVector result = topoSortRegion(*rootRegion); + assert(result.size() == toSort.size() && + "expected all operations to be present in the result"); + return result; + } + +private: + /// Computes the closest common ancestor region of all operations in `toSort`. + Region *findCommonAncestorRegion() { + // Map to count the number of times a region was encountered. + DenseMap regionCounts; + size_t expectedCount = toSort.size(); + + // Walk the region tree for each operation towards the root and add to the + // region count. + Region *res = nullptr; + for (Operation *op : toSort) { + Region *current = op->getParentRegion(); + // Store the block as an ancestor block. + ancestorBlocks.insert(op->getBlock()); + while (current) { + // Insert or update the count and compare it. + if (++regionCounts[current] == expectedCount) { + res = current; + break; + } + ancestorBlocks.insert(current->getParentOp()->getBlock()); + current = current->getParentRegion(); + } + } + auto firstRange = llvm::make_first_range(regionCounts); + ancestorRegions.insert(firstRange.begin(), firstRange.end()); + return res; + } + + /// Performs the dominance respecting IR walk to collect the topological order + /// of the operation to sort. + SetVector topoSortRegion(Region &rootRegion) { + using StackT = PointerUnion; + + SetVector result; + // Stack that stores the different IR constructs to traverse. + SmallVector stack; + stack.push_back(&rootRegion); + + // Traverse the IR in a dominance respecting pre-order walk. + while (!stack.empty()) { + StackT current = stack.pop_back_val(); + if (auto *region = dyn_cast(current)) { + // A region's blocks need to be traversed in dominance order. + SetVector sortedBlocks = getBlocksSortedByDominance(*region); + for (Block *block : llvm::reverse(sortedBlocks)) { + // Only add blocks to the stack that are ancestors of the operations + // to sort. + if (ancestorBlocks.contains(block)) + stack.push_back(block); + } + continue; + } + + if (auto *block = dyn_cast(current)) { + // Add all of the blocks operations to the stack. + for (Operation &op : llvm::reverse(*block)) + stack.push_back(&op); + continue; + } + + auto *op = cast(current); + if (toSort.contains(op)) + result.insert(op); + + // Add all the subregions that are ancestors of the operations to sort. + for (Region &subRegion : op->getRegions()) + if (ancestorRegions.contains(&subRegion)) + stack.push_back(&subRegion); + } + return result; + } + + /// Operations to sort. + const SetVector &toSort; + /// Set containing all the ancestor regions of the operations to sort. + DenseSet ancestorRegions; + /// Set containing all the ancestor blocks of the operations to sort. + DenseSet ancestorBlocks; +}; +} // namespace + +SetVector +mlir::topologicalSort(const SetVector &toSort) { + return TopoSortHelper(toSort).sort(); +} diff --git a/mlir/lib/Conversion/VectorToGPU/VectorToGPU.cpp b/mlir/lib/Conversion/VectorToGPU/VectorToGPU.cpp index 332f0a2eecfc..4496c2bc5fe8 100644 --- a/mlir/lib/Conversion/VectorToGPU/VectorToGPU.cpp +++ b/mlir/lib/Conversion/VectorToGPU/VectorToGPU.cpp @@ -15,6 +15,7 @@ #include #include "mlir/Analysis/SliceAnalysis.h" +#include "mlir/Analysis/TopologicalSortUtils.h" #include "mlir/Dialect/Affine/IR/AffineOps.h" #include "mlir/Dialect/Arith/IR/Arith.h" #include "mlir/Dialect/GPU/IR/GPUDialect.h" diff --git a/mlir/lib/Dialect/Affine/Utils/LoopFusionUtils.cpp b/mlir/lib/Dialect/Affine/Utils/LoopFusionUtils.cpp index 84ae4b52dcf4..7f3e43d0b4cd 100644 --- a/mlir/lib/Dialect/Affine/Utils/LoopFusionUtils.cpp +++ b/mlir/lib/Dialect/Affine/Utils/LoopFusionUtils.cpp @@ -12,6 +12,7 @@ #include "mlir/Dialect/Affine/LoopFusionUtils.h" #include "mlir/Analysis/SliceAnalysis.h" +#include "mlir/Analysis/TopologicalSortUtils.h" #include "mlir/Dialect/Affine/Analysis/AffineAnalysis.h" #include "mlir/Dialect/Affine/Analysis/LoopAnalysis.h" #include "mlir/Dialect/Affine/Analysis/Utils.h" diff --git a/mlir/lib/Dialect/ArmSME/Transforms/TileAllocation.cpp b/mlir/lib/Dialect/ArmSME/Transforms/TileAllocation.cpp index acbbbe9932e1..733e758b4390 100644 --- a/mlir/lib/Dialect/ArmSME/Transforms/TileAllocation.cpp +++ b/mlir/lib/Dialect/ArmSME/Transforms/TileAllocation.cpp @@ -46,6 +46,7 @@ //===----------------------------------------------------------------------===// #include "mlir/Analysis/Liveness.h" +#include "mlir/Analysis/TopologicalSortUtils.h" #include "mlir/Dialect/ArmSME/IR/ArmSME.h" #include "mlir/Dialect/ArmSME/Transforms/Passes.h" #include "mlir/Dialect/ArmSME/Transforms/Transforms.h" diff --git a/mlir/lib/Target/LLVMIR/Dialect/OpenACC/OpenACCToLLVMIRTranslation.cpp b/mlir/lib/Target/LLVMIR/Dialect/OpenACC/OpenACCToLLVMIRTranslation.cpp index eeda245ce969..d9cf85e4aeca 100644 --- a/mlir/lib/Target/LLVMIR/Dialect/OpenACC/OpenACCToLLVMIRTranslation.cpp +++ b/mlir/lib/Target/LLVMIR/Dialect/OpenACC/OpenACCToLLVMIRTranslation.cpp @@ -12,6 +12,7 @@ //===----------------------------------------------------------------------===// #include "mlir/Target/LLVMIR/Dialect/OpenACC/OpenACCToLLVMIRTranslation.h" +#include "mlir/Analysis/TopologicalSortUtils.h" #include "mlir/Dialect/LLVMIR/LLVMDialect.h" #include "mlir/Dialect/OpenACC/OpenACC.h" #include "mlir/IR/BuiltinOps.h" @@ -19,7 +20,6 @@ #include "mlir/Support/LLVM.h" #include "mlir/Target/LLVMIR/Dialect/OpenMPCommon.h" #include "mlir/Target/LLVMIR/ModuleTranslation.h" -#include "mlir/Transforms/RegionUtils.h" #include "llvm/ADT/TypeSwitch.h" #include "llvm/Frontend/OpenMP/OMPConstants.h" diff --git a/mlir/lib/Target/LLVMIR/Dialect/OpenMP/OpenMPToLLVMIRTranslation.cpp b/mlir/lib/Target/LLVMIR/Dialect/OpenMP/OpenMPToLLVMIRTranslation.cpp index 34b6903f8da0..9d125b7f1180 100644 --- a/mlir/lib/Target/LLVMIR/Dialect/OpenMP/OpenMPToLLVMIRTranslation.cpp +++ b/mlir/lib/Target/LLVMIR/Dialect/OpenMP/OpenMPToLLVMIRTranslation.cpp @@ -11,6 +11,7 @@ // //===----------------------------------------------------------------------===// #include "mlir/Target/LLVMIR/Dialect/OpenMP/OpenMPToLLVMIRTranslation.h" +#include "mlir/Analysis/TopologicalSortUtils.h" #include "mlir/Dialect/LLVMIR/LLVMDialect.h" #include "mlir/Dialect/OpenMP/OpenMPDialect.h" #include "mlir/Dialect/OpenMP/OpenMPInterfaces.h" diff --git a/mlir/lib/Target/LLVMIR/ModuleTranslation.cpp b/mlir/lib/Target/LLVMIR/ModuleTranslation.cpp index cf3257c8b9b8..1ec0736ec08b 100644 --- a/mlir/lib/Target/LLVMIR/ModuleTranslation.cpp +++ b/mlir/lib/Target/LLVMIR/ModuleTranslation.cpp @@ -16,6 +16,7 @@ #include "AttrKindDetail.h" #include "DebugTranslation.h" #include "LoopAnnotationTranslation.h" +#include "mlir/Analysis/TopologicalSortUtils.h" #include "mlir/Dialect/DLTI/DLTI.h" #include "mlir/Dialect/LLVMIR/LLVMDialect.h" #include "mlir/Dialect/LLVMIR/LLVMInterfaces.h" @@ -33,7 +34,6 @@ #include "mlir/Support/LogicalResult.h" #include "mlir/Target/LLVMIR/LLVMTranslationInterface.h" #include "mlir/Target/LLVMIR/TypeToLLVM.h" -#include "mlir/Transforms/RegionUtils.h" #include "llvm/ADT/PostOrderIterator.h" #include "llvm/ADT/SetVector.h" diff --git a/mlir/lib/Transforms/Mem2Reg.cpp b/mlir/lib/Transforms/Mem2Reg.cpp index e2e240ad865c..a452cc3fae8a 100644 --- a/mlir/lib/Transforms/Mem2Reg.cpp +++ b/mlir/lib/Transforms/Mem2Reg.cpp @@ -9,6 +9,7 @@ #include "mlir/Transforms/Mem2Reg.h" #include "mlir/Analysis/DataLayoutAnalysis.h" #include "mlir/Analysis/SliceAnalysis.h" +#include "mlir/Analysis/TopologicalSortUtils.h" #include "mlir/IR/Builders.h" #include "mlir/IR/Dominance.h" #include "mlir/IR/PatternMatch.h" @@ -16,7 +17,6 @@ #include "mlir/Interfaces/ControlFlowInterfaces.h" #include "mlir/Interfaces/MemorySlotInterfaces.h" #include "mlir/Transforms/Passes.h" -#include "mlir/Transforms/RegionUtils.h" #include "llvm/ADT/STLExtras.h" #include "llvm/Support/GenericIteratedDominanceFrontier.h" diff --git a/mlir/lib/Transforms/SROA.cpp b/mlir/lib/Transforms/SROA.cpp index 67cbade07bc9..39f7256fb789 100644 --- a/mlir/lib/Transforms/SROA.cpp +++ b/mlir/lib/Transforms/SROA.cpp @@ -9,6 +9,7 @@ #include "mlir/Transforms/SROA.h" #include "mlir/Analysis/DataLayoutAnalysis.h" #include "mlir/Analysis/SliceAnalysis.h" +#include "mlir/Analysis/TopologicalSortUtils.h" #include "mlir/Interfaces/MemorySlotInterfaces.h" #include "mlir/Transforms/Passes.h" diff --git a/mlir/lib/Transforms/TopologicalSort.cpp b/mlir/lib/Transforms/TopologicalSort.cpp index 1219968fb369..528f6ef67602 100644 --- a/mlir/lib/Transforms/TopologicalSort.cpp +++ b/mlir/lib/Transforms/TopologicalSort.cpp @@ -8,8 +8,8 @@ #include "mlir/Transforms/Passes.h" +#include "mlir/Analysis/TopologicalSortUtils.h" #include "mlir/IR/RegionKindInterface.h" -#include "mlir/Transforms/TopologicalSortUtils.h" namespace mlir { #define GEN_PASS_DEF_TOPOLOGICALSORT diff --git a/mlir/lib/Transforms/Utils/CMakeLists.txt b/mlir/lib/Transforms/Utils/CMakeLists.txt index d6aac0e2da4f..b5788c679edc 100644 --- a/mlir/lib/Transforms/Utils/CMakeLists.txt +++ b/mlir/lib/Transforms/Utils/CMakeLists.txt @@ -10,7 +10,6 @@ add_mlir_library(MLIRTransformUtils LoopInvariantCodeMotionUtils.cpp OneToNTypeConversion.cpp RegionUtils.cpp - TopologicalSortUtils.cpp ADDITIONAL_HEADER_DIRS ${MLIR_MAIN_INCLUDE_DIR}/mlir/Transforms diff --git a/mlir/lib/Transforms/Utils/RegionUtils.cpp b/mlir/lib/Transforms/Utils/RegionUtils.cpp index 192f59b35329..b5e641d39fc0 100644 --- a/mlir/lib/Transforms/Utils/RegionUtils.cpp +++ b/mlir/lib/Transforms/Utils/RegionUtils.cpp @@ -7,6 +7,7 @@ //===----------------------------------------------------------------------===// #include "mlir/Transforms/RegionUtils.h" +#include "mlir/Analysis/TopologicalSortUtils.h" #include "mlir/IR/Block.h" #include "mlir/IR/IRMapping.h" #include "mlir/IR/Operation.h" @@ -15,11 +16,9 @@ #include "mlir/IR/Value.h" #include "mlir/Interfaces/ControlFlowInterfaces.h" #include "mlir/Interfaces/SideEffectInterfaces.h" -#include "mlir/Transforms/TopologicalSortUtils.h" #include "llvm/ADT/DepthFirstIterator.h" #include "llvm/ADT/PostOrderIterator.h" -#include "llvm/ADT/SmallSet.h" #include @@ -836,19 +835,3 @@ LogicalResult mlir::simplifyRegions(RewriterBase &rewriter, return success(eliminatedBlocks || eliminatedOpsOrArgs || mergedIdenticalBlocks); } - -SetVector mlir::getBlocksSortedByDominance(Region ®ion) { - // For each block that has not been visited yet (i.e. that has no - // predecessors), add it to the list as well as its successors. - SetVector blocks; - for (Block &b : region) { - if (blocks.count(&b) == 0) { - llvm::ReversePostOrderTraversal traversal(&b); - blocks.insert(traversal.begin(), traversal.end()); - } - } - assert(blocks.size() == region.getBlocks().size() && - "some blocks are not sorted"); - - return blocks; -} diff --git a/mlir/lib/Transforms/ViewOpGraph.cpp b/mlir/lib/Transforms/ViewOpGraph.cpp index c2eb2b893cea..b3c0a06c96fe 100644 --- a/mlir/lib/Transforms/ViewOpGraph.cpp +++ b/mlir/lib/Transforms/ViewOpGraph.cpp @@ -8,12 +8,12 @@ #include "mlir/Transforms/ViewOpGraph.h" +#include "mlir/Analysis/TopologicalSortUtils.h" #include "mlir/IR/Block.h" #include "mlir/IR/BuiltinTypes.h" #include "mlir/IR/Operation.h" #include "mlir/Pass/Pass.h" #include "mlir/Support/IndentedOstream.h" -#include "mlir/Transforms/TopologicalSortUtils.h" #include "llvm/Support/Format.h" #include "llvm/Support/GraphWriter.h" #include diff --git a/mlir/test/Analysis/test-topoligical-sort.mlir b/mlir/test/Analysis/test-topoligical-sort.mlir index 860858640205..150aff854fc8 100644 --- a/mlir/test/Analysis/test-topoligical-sort.mlir +++ b/mlir/test/Analysis/test-topoligical-sort.mlir @@ -1,21 +1,38 @@ -// RUN: mlir-opt %s -pass-pipeline="builtin.module(func.func(test-print-topological-sort))" 2>&1 | FileCheck %s +// RUN: mlir-opt %s -pass-pipeline="builtin.module(func.func(test-print-topological-sort))" --split-input-file | FileCheck %s -// CHECK-LABEL: Testing : region -// CHECK: arith.addi {{.*}} : index -// CHECK-NEXT: scf.for -// CHECK: } {__test_sort_original_idx__ = 2 : i64} -// CHECK-NEXT: arith.addi {{.*}} : i32 -// CHECK-NEXT: arith.subi {{.*}} : i32 -func.func @region( - %arg0 : index, %arg1 : index, %arg2 : index, %arg3 : index, - %arg4 : i32, %arg5 : i32, %arg6 : i32, - %buffer : memref) { - %0 = arith.addi %arg4, %arg5 {__test_sort_original_idx__ = 0} : i32 - %idx = arith.addi %arg0, %arg1 {__test_sort_original_idx__ = 3} : index - scf.for %arg7 = %idx to %arg2 step %arg3 { - %2 = arith.addi %0, %arg5 : i32 - %3 = arith.subi %2, %arg6 {__test_sort_original_idx__ = 1} : i32 - memref.store %3, %buffer[] : memref - } {__test_sort_original_idx__ = 2} +// CHECK-LABEL: single_element +func.func @single_element() { + // CHECK: test_sort_index = 0 + return {test_to_sort} +} + +// ----- + +// CHECK-LABEL: @simple_region +func.func @simple_region(%cond: i1) { + // CHECK: test_sort_index = 0 + %0 = arith.constant {test_to_sort} 42 : i32 + scf.if %cond { + %1 = arith.addi %0, %0 : i32 + // CHECK: test_sort_index = 2 + %2 = arith.subi %0, %1 {test_to_sort} : i32 + // CHECK: test_sort_index = 1 + } {test_to_sort} + return +} + +// ----- + +// CHECK-LABEL: @multi_region +func.func @multi_region(%cond: i1) { + scf.if %cond { + // CHECK: test_sort_index = 0 + %0 = arith.constant {test_to_sort} 42 : i32 + } + + scf.if %cond { + // CHECK: test_sort_index = 1 + %0 = arith.constant {test_to_sort} 24 : i32 + } return } diff --git a/mlir/test/Transforms/test-toposort.mlir b/mlir/test/Analysis/test-toposort.mlir similarity index 100% rename from mlir/test/Transforms/test-toposort.mlir rename to mlir/test/Analysis/test-toposort.mlir diff --git a/mlir/test/Dialect/Affine/slicing-utils.mlir b/mlir/test/Dialect/Affine/slicing-utils.mlir index 74379978fdf8..0848a924b9d9 100644 --- a/mlir/test/Dialect/Affine/slicing-utils.mlir +++ b/mlir/test/Dialect/Affine/slicing-utils.mlir @@ -28,15 +28,15 @@ func.func @slicing_test() { // BWD: matched: %[[v1:.*]] {{.*}} backward static slice: // // FWDBWD: matched: %[[v1:.*]] {{.*}} static slice: - // FWDBWD-DAG: %[[v4:.*]] = "slicing-test-op"() : () -> i4 - // FWDBWD-DAG: %[[v3:.*]] = "slicing-test-op"() : () -> i3 - // FWDBWD-NEXT: %[[v6:.*]] = "slicing-test-op"(%[[v3]], %[[v4]]) : (i3, i4) -> i6 - // FWDBWD-DAG: %[[v2:.*]] = "slicing-test-op"() : () -> i2 - // FWDBWD-DAG: %[[v1:.*]] = "slicing-test-op"() : () -> i1 - // FWDBWD-NEXT: %[[v5:.*]] = "slicing-test-op"(%[[v1]], %[[v2]]) : (i1, i2) -> i5 - // FWDBWD-DAG: %[[v8:.*]] = "slicing-test-op"(%[[v5]], %[[v6]]) : (i5, i6) -> i8 - // FWDBWD-DAG: %[[v7:.*]] = "slicing-test-op"(%[[v1]], %[[v5]]) : (i1, i5) -> i7 - // FWDBWD-NEXT: %[[v9:.*]] = "slicing-test-op"(%[[v7]], %[[v8]]) : (i7, i8) -> i9 + // FWDBWD: %[[v1:.*]] = "slicing-test-op"() : () -> i1 + // FWDBWD: %[[v2:.*]] = "slicing-test-op"() : () -> i2 + // FWDBWD: %[[v3:.*]] = "slicing-test-op"() : () -> i3 + // FWDBWD: %[[v4:.*]] = "slicing-test-op"() : () -> i4 + // FWDBWD: %[[v5:.*]] = "slicing-test-op"(%[[v1]], %[[v2]]) : (i1, i2) -> i5 + // FWDBWD: %[[v6:.*]] = "slicing-test-op"(%[[v3]], %[[v4]]) : (i3, i4) -> i6 + // FWDBWD: %[[v7:.*]] = "slicing-test-op"(%[[v1]], %[[v5]]) : (i1, i5) -> i7 + // FWDBWD: %[[v8:.*]] = "slicing-test-op"(%[[v5]], %[[v6]]) : (i5, i6) -> i8 + // FWDBWD: %[[v9:.*]] = "slicing-test-op"(%[[v7]], %[[v8]]) : (i7, i8) -> i9 %1 = "slicing-test-op" () : () -> i1 @@ -49,15 +49,15 @@ func.func @slicing_test() { // BWD: matched: %[[v2:.*]] {{.*}} backward static slice: // // FWDBWD-NEXT: matched: %[[v2:.*]] {{.*}} static slice: - // FWDBWD-DAG: %[[v4:.*]] = "slicing-test-op"() : () -> i4 - // FWDBWD-DAG: %[[v3:.*]] = "slicing-test-op"() : () -> i3 - // FWDBWD-NEXT: %[[v6:.*]] = "slicing-test-op"(%[[v3]], %[[v4]]) : (i3, i4) -> i6 - // FWDBWD-DAG: %[[v2:.*]] = "slicing-test-op"() : () -> i2 - // FWDBWD-DAG: %[[v1:.*]] = "slicing-test-op"() : () -> i1 - // FWDBWD-NEXT: %[[v5:.*]] = "slicing-test-op"(%[[v1]], %[[v2]]) : (i1, i2) -> i5 - // FWDBWD-DAG: %[[v8:.*]] = "slicing-test-op"(%[[v5]], %[[v6]]) : (i5, i6) -> i8 - // FWDBWD-DAG: %[[v7:.*]] = "slicing-test-op"(%[[v1]], %[[v5]]) : (i1, i5) -> i7 - // FWDBWD-NEXT: %[[v9:.*]] = "slicing-test-op"(%[[v7]], %[[v8]]) : (i7, i8) -> i9 + // FWDBWD: %[[v1:.*]] = "slicing-test-op"() : () -> i1 + // FWDBWD: %[[v2:.*]] = "slicing-test-op"() : () -> i2 + // FWDBWD: %[[v3:.*]] = "slicing-test-op"() : () -> i3 + // FWDBWD: %[[v4:.*]] = "slicing-test-op"() : () -> i4 + // FWDBWD: %[[v5:.*]] = "slicing-test-op"(%[[v1]], %[[v2]]) : (i1, i2) -> i5 + // FWDBWD: %[[v6:.*]] = "slicing-test-op"(%[[v3]], %[[v4]]) : (i3, i4) -> i6 + // FWDBWD: %[[v7:.*]] = "slicing-test-op"(%[[v1]], %[[v5]]) : (i1, i5) -> i7 + // FWDBWD: %[[v8:.*]] = "slicing-test-op"(%[[v5]], %[[v6]]) : (i5, i6) -> i8 + // FWDBWD: %[[v9:.*]] = "slicing-test-op"(%[[v7]], %[[v8]]) : (i7, i8) -> i9 %2 = "slicing-test-op" () : () -> i2 @@ -69,15 +69,15 @@ func.func @slicing_test() { // BWD: matched: %[[v3:.*]] {{.*}} backward static slice: // // FWDBWD-NEXT: matched: %[[v3:.*]] {{.*}} static slice: - // FWDBWD-DAG: %[[v2:.*]] = "slicing-test-op"() : () -> i2 - // FWDBWD-DAG: %[[v1:.*]] = "slicing-test-op"() : () -> i1 - // FWDBWD-NEXT: %[[v5:.*]] = "slicing-test-op"(%[[v1]], %[[v2]]) : (i1, i2) -> i5 - // FWDBWD-NEXT: %[[v7:.*]] = "slicing-test-op"(%[[v1]], %[[v5]]) : (i1, i5) -> i7 - // FWDBWD-DAG: %[[v4:.*]] = "slicing-test-op"() : () -> i4 - // FWDBWD-DAG: %[[v3:.*]] = "slicing-test-op"() : () -> i3 - // FWDBWD-NEXT: %[[v6:.*]] = "slicing-test-op"(%[[v3]], %[[v4]]) : (i3, i4) -> i6 - // FWDBWD-NEXT: %[[v8:.*]] = "slicing-test-op"(%[[v5]], %[[v6]]) : (i5, i6) -> i8 - // FWDBWD-NEXT: %[[v9:.*]] = "slicing-test-op"(%[[v7]], %[[v8]]) : (i7, i8) -> i9 + // FWDBWD: %[[v1:.*]] = "slicing-test-op"() : () -> i1 + // FWDBWD: %[[v2:.*]] = "slicing-test-op"() : () -> i2 + // FWDBWD: %[[v3:.*]] = "slicing-test-op"() : () -> i3 + // FWDBWD: %[[v4:.*]] = "slicing-test-op"() : () -> i4 + // FWDBWD: %[[v5:.*]] = "slicing-test-op"(%[[v1]], %[[v2]]) : (i1, i2) -> i5 + // FWDBWD: %[[v6:.*]] = "slicing-test-op"(%[[v3]], %[[v4]]) : (i3, i4) -> i6 + // FWDBWD: %[[v7:.*]] = "slicing-test-op"(%[[v1]], %[[v5]]) : (i1, i5) -> i7 + // FWDBWD: %[[v8:.*]] = "slicing-test-op"(%[[v5]], %[[v6]]) : (i5, i6) -> i8 + // FWDBWD: %[[v9:.*]] = "slicing-test-op"(%[[v7]], %[[v8]]) : (i7, i8) -> i9 %3 = "slicing-test-op" () : () -> i3 @@ -89,15 +89,15 @@ func.func @slicing_test() { // BWD: matched: %[[v4:.*]] {{.*}} backward static slice: // // FWDBWD-NEXT: matched: %[[v4:.*]] {{.*}} static slice: - // FWDBWD-DAG: %[[v2:.*]] = "slicing-test-op"() : () -> i2 - // FWDBWD-DAG: %[[v1:.*]] = "slicing-test-op"() : () -> i1 - // FWDBWD-NEXT: %[[v5:.*]] = "slicing-test-op"(%[[v1]], %[[v2]]) : (i1, i2) -> i5 - // FWDBWD-NEXT: %[[v7:.*]] = "slicing-test-op"(%[[v1]], %[[v5]]) : (i1, i5) -> i7 - // FWDBWD-DAG: %[[v4:.*]] = "slicing-test-op"() : () -> i4 - // FWDBWD-DAG: %[[v3:.*]] = "slicing-test-op"() : () -> i3 - // FWDBWD-NEXT: %[[v6:.*]] = "slicing-test-op"(%[[v3]], %[[v4]]) : (i3, i4) -> i6 - // FWDBWD-NEXT: %[[v8:.*]] = "slicing-test-op"(%[[v5]], %[[v6]]) : (i5, i6) -> i8 - // FWDBWD-NEXT: %[[v9:.*]] = "slicing-test-op"(%[[v7]], %[[v8]]) : (i7, i8) -> i9 + // FWDBWD: %[[v1:.*]] = "slicing-test-op"() : () -> i1 + // FWDBWD: %[[v2:.*]] = "slicing-test-op"() : () -> i2 + // FWDBWD: %[[v3:.*]] = "slicing-test-op"() : () -> i3 + // FWDBWD: %[[v4:.*]] = "slicing-test-op"() : () -> i4 + // FWDBWD: %[[v5:.*]] = "slicing-test-op"(%[[v1]], %[[v2]]) : (i1, i2) -> i5 + // FWDBWD: %[[v6:.*]] = "slicing-test-op"(%[[v3]], %[[v4]]) : (i3, i4) -> i6 + // FWDBWD: %[[v7:.*]] = "slicing-test-op"(%[[v1]], %[[v5]]) : (i1, i5) -> i7 + // FWDBWD: %[[v8:.*]] = "slicing-test-op"(%[[v5]], %[[v6]]) : (i5, i6) -> i8 + // FWDBWD: %[[v9:.*]] = "slicing-test-op"(%[[v7]], %[[v8]]) : (i7, i8) -> i9 %4 = "slicing-test-op" () : () -> i4 @@ -111,15 +111,15 @@ func.func @slicing_test() { // BWD-DAG: %[[v2:.*]] = "slicing-test-op"() : () -> i2 // // FWDBWD-NEXT: matched: %[[v5:.*]] {{.*}} static slice: - // FWDBWD-DAG: %[[v4:.*]] = "slicing-test-op"() : () -> i4 - // FWDBWD-DAG: %[[v3:.*]] = "slicing-test-op"() : () -> i3 - // FWDBWD-NEXT: %[[v6:.*]] = "slicing-test-op"(%[[v3]], %[[v4]]) : (i3, i4) -> i6 - // FWDBWD-DAG: %[[v2:.*]] = "slicing-test-op"() : () -> i2 - // FWDBWD-DAG: %[[v1:.*]] = "slicing-test-op"() : () -> i1 - // FWDBWD-NEXT: %[[v5:.*]] = "slicing-test-op"(%[[v1]], %[[v2]]) : (i1, i2) -> i5 - // FWDBWD-DAG: %[[v8:.*]] = "slicing-test-op"(%[[v5]], %[[v6]]) : (i5, i6) -> i8 - // FWDBWD-DAG: %[[v7:.*]] = "slicing-test-op"(%[[v1]], %[[v5]]) : (i1, i5) -> i7 - // FWDBWD-NEXT: %[[v9:.*]] = "slicing-test-op"(%[[v7]], %[[v8]]) : (i7, i8) -> i9 + // FWDBWD: %[[v1:.*]] = "slicing-test-op"() : () -> i1 + // FWDBWD: %[[v2:.*]] = "slicing-test-op"() : () -> i2 + // FWDBWD: %[[v3:.*]] = "slicing-test-op"() : () -> i3 + // FWDBWD: %[[v4:.*]] = "slicing-test-op"() : () -> i4 + // FWDBWD: %[[v5:.*]] = "slicing-test-op"(%[[v1]], %[[v2]]) : (i1, i2) -> i5 + // FWDBWD: %[[v6:.*]] = "slicing-test-op"(%[[v3]], %[[v4]]) : (i3, i4) -> i6 + // FWDBWD: %[[v7:.*]] = "slicing-test-op"(%[[v1]], %[[v5]]) : (i1, i5) -> i7 + // FWDBWD: %[[v8:.*]] = "slicing-test-op"(%[[v5]], %[[v6]]) : (i5, i6) -> i8 + // FWDBWD: %[[v9:.*]] = "slicing-test-op"(%[[v7]], %[[v8]]) : (i7, i8) -> i9 %5 = "slicing-test-op" (%1, %2) : (i1, i2) -> i5 @@ -132,15 +132,15 @@ func.func @slicing_test() { // BWD-DAG: %[[v4:.*]] = "slicing-test-op"() : () -> i4 // // FWDBWD-NEXT: matched: %[[v6:.*]] {{.*}} static slice: - // FWDBWD-DAG: %[[v2:.*]] = "slicing-test-op"() : () -> i2 - // FWDBWD-DAG: %[[v1:.*]] = "slicing-test-op"() : () -> i1 - // FWDBWD-NEXT: %[[v5:.*]] = "slicing-test-op"(%[[v1]], %[[v2]]) : (i1, i2) -> i5 - // FWDBWD-NEXT: %[[v7:.*]] = "slicing-test-op"(%[[v1]], %[[v5]]) : (i1, i5) -> i7 - // FWDBWD-DAG: %[[v4:.*]] = "slicing-test-op"() : () -> i4 - // FWDBWD-DAG: %[[v3:.*]] = "slicing-test-op"() : () -> i3 - // FWDBWD-NEXT: %[[v6:.*]] = "slicing-test-op"(%[[v3]], %[[v4]]) : (i3, i4) -> i6 - // FWDBWD-NEXT: %[[v8:.*]] = "slicing-test-op"(%[[v5]], %[[v6]]) : (i5, i6) -> i8 - // FWDBWD-NEXT: %[[v9:.*]] = "slicing-test-op"(%[[v7]], %[[v8]]) : (i7, i8) -> i9 + // FWDBWD: %[[v1:.*]] = "slicing-test-op"() : () -> i1 + // FWDBWD: %[[v2:.*]] = "slicing-test-op"() : () -> i2 + // FWDBWD: %[[v3:.*]] = "slicing-test-op"() : () -> i3 + // FWDBWD: %[[v4:.*]] = "slicing-test-op"() : () -> i4 + // FWDBWD: %[[v5:.*]] = "slicing-test-op"(%[[v1]], %[[v2]]) : (i1, i2) -> i5 + // FWDBWD: %[[v6:.*]] = "slicing-test-op"(%[[v3]], %[[v4]]) : (i3, i4) -> i6 + // FWDBWD: %[[v7:.*]] = "slicing-test-op"(%[[v1]], %[[v5]]) : (i1, i5) -> i7 + // FWDBWD: %[[v8:.*]] = "slicing-test-op"(%[[v5]], %[[v6]]) : (i5, i6) -> i8 + // FWDBWD: %[[v9:.*]] = "slicing-test-op"(%[[v7]], %[[v8]]) : (i7, i8) -> i9 %6 = "slicing-test-op" (%3, %4) : (i3, i4) -> i6 @@ -153,15 +153,15 @@ func.func @slicing_test() { // BWD-NEXT: %[[v5:.*]] = "slicing-test-op"(%[[v1]], %[[v2]]) : (i1, i2) -> i5 // // FWDBWD-NEXT: matched: %[[v7:.*]] {{.*}} static slice: - // FWDBWD-DAG: %[[v4:.*]] = "slicing-test-op"() : () -> i4 - // FWDBWD-DAG: %[[v3:.*]] = "slicing-test-op"() : () -> i3 - // FWDBWD-NEXT: %[[v6:.*]] = "slicing-test-op"(%[[v3]], %[[v4]]) : (i3, i4) -> i6 - // FWDBWD-DAG: %[[v2:.*]] = "slicing-test-op"() : () -> i2 - // FWDBWD-DAG: %[[v1:.*]] = "slicing-test-op"() : () -> i1 + // FWDBWD: %[[v1:.*]] = "slicing-test-op"() : () -> i1 + // FWDBWD: %[[v2:.*]] = "slicing-test-op"() : () -> i2 + // FWDBWD: %[[v3:.*]] = "slicing-test-op"() : () -> i3 + // FWDBWD: %[[v4:.*]] = "slicing-test-op"() : () -> i4 // FWDBWD: %[[v5:.*]] = "slicing-test-op"(%[[v1]], %[[v2]]) : (i1, i2) -> i5 - // FWDBWD-DAG: %[[v8:.*]] = "slicing-test-op"(%[[v5]], %[[v6]]) : (i5, i6) -> i8 - // FWDBWD-DAG: %[[v7:.*]] = "slicing-test-op"(%[[v1]], %[[v5]]) : (i1, i5) -> i7 - // FWDBWD-NEXT: %[[v9:.*]] = "slicing-test-op"(%[[v7]], %[[v8]]) : (i7, i8) -> i9 + // FWDBWD: %[[v6:.*]] = "slicing-test-op"(%[[v3]], %[[v4]]) : (i3, i4) -> i6 + // FWDBWD: %[[v7:.*]] = "slicing-test-op"(%[[v1]], %[[v5]]) : (i1, i5) -> i7 + // FWDBWD: %[[v8:.*]] = "slicing-test-op"(%[[v5]], %[[v6]]) : (i5, i6) -> i8 + // FWDBWD: %[[v9:.*]] = "slicing-test-op"(%[[v7]], %[[v8]]) : (i7, i8) -> i9 %7 = "slicing-test-op" (%1, %5) : (i1, i5) -> i7 @@ -177,15 +177,15 @@ func.func @slicing_test() { // BWD-NEXT: %[[v6:.*]] = "slicing-test-op"(%[[v3]], %[[v4]]) : (i3, i4) -> i6 // // FWDBWD-NEXT: matched: %[[v8:.*]] {{.*}} static slice: - // FWDBWD-DAG: %[[v4:.*]] = "slicing-test-op"() : () -> i4 - // FWDBWD-DAG: %[[v3:.*]] = "slicing-test-op"() : () -> i3 - // FWDBWD-NEXT: %[[v6:.*]] = "slicing-test-op"(%[[v3]], %[[v4]]) : (i3, i4) -> i6 - // FWDBWD-DAG: %[[v2:.*]] = "slicing-test-op"() : () -> i2 - // FWDBWD-DAG: %[[v1:.*]] = "slicing-test-op"() : () -> i1 - // FWDBWD-NEXT: %[[v5:.*]] = "slicing-test-op"(%[[v1]], %[[v2]]) : (i1, i2) -> i5 - // FWDBWD-DAG: %[[v8:.*]] = "slicing-test-op"(%[[v5]], %[[v6]]) : (i5, i6) -> i8 - // FWDBWD-DAG: %[[v7:.*]] = "slicing-test-op"(%[[v1]], %[[v5]]) : (i1, i5) -> i7 - // FWDBWD-NEXT: %[[v9:.*]] = "slicing-test-op"(%[[v7]], %[[v8]]) : (i7, i8) -> i9 + // FWDBWD: %[[v1:.*]] = "slicing-test-op"() : () -> i1 + // FWDBWD: %[[v2:.*]] = "slicing-test-op"() : () -> i2 + // FWDBWD: %[[v3:.*]] = "slicing-test-op"() : () -> i3 + // FWDBWD: %[[v4:.*]] = "slicing-test-op"() : () -> i4 + // FWDBWD: %[[v5:.*]] = "slicing-test-op"(%[[v1]], %[[v2]]) : (i1, i2) -> i5 + // FWDBWD: %[[v6:.*]] = "slicing-test-op"(%[[v3]], %[[v4]]) : (i3, i4) -> i6 + // FWDBWD: %[[v7:.*]] = "slicing-test-op"(%[[v1]], %[[v5]]) : (i1, i5) -> i7 + // FWDBWD: %[[v8:.*]] = "slicing-test-op"(%[[v5]], %[[v6]]) : (i5, i6) -> i8 + // FWDBWD: %[[v9:.*]] = "slicing-test-op"(%[[v7]], %[[v8]]) : (i7, i8) -> i9 %8 = "slicing-test-op" (%5, %6) : (i5, i6) -> i8 @@ -202,15 +202,15 @@ func.func @slicing_test() { // BWD-NEXT: %[[v8:.*]] = "slicing-test-op"(%[[v5]], %[[v6]]) : (i5, i6) -> i8 // // FWDBWD-NEXT: matched: %[[v9:.*]] {{.*}} static slice: - // FWDBWD-DAG: %[[v4:.*]] = "slicing-test-op"() : () -> i4 - // FWDBWD-DAG: %[[v3:.*]] = "slicing-test-op"() : () -> i3 - // FWDBWD-NEXT: %[[v6:.*]] = "slicing-test-op"(%[[v3]], %[[v4]]) : (i3, i4) -> i6 - // FWDBWD-DAG: %[[v2:.*]] = "slicing-test-op"() : () -> i2 - // FWDBWD-DAG: %[[v1:.*]] = "slicing-test-op"() : () -> i1 - // FWDBWD-NEXT: %[[v5:.*]] = "slicing-test-op"(%[[v1]], %[[v2]]) : (i1, i2) -> i5 - // FWDBWD-DAG: %[[v8:.*]] = "slicing-test-op"(%[[v5]], %[[v6]]) : (i5, i6) -> i8 - // FWDBWD-DAG: %[[v7:.*]] = "slicing-test-op"(%[[v1]], %[[v5]]) : (i1, i5) -> i7 - // FWDBWD-NEXT: %[[v9:.*]] = "slicing-test-op"(%[[v7]], %[[v8]]) : (i7, i8) -> i9 + // FWDBWD: %[[v1:.*]] = "slicing-test-op"() : () -> i1 + // FWDBWD: %[[v2:.*]] = "slicing-test-op"() : () -> i2 + // FWDBWD: %[[v3:.*]] = "slicing-test-op"() : () -> i3 + // FWDBWD: %[[v4:.*]] = "slicing-test-op"() : () -> i4 + // FWDBWD: %[[v5:.*]] = "slicing-test-op"(%[[v1]], %[[v2]]) : (i1, i2) -> i5 + // FWDBWD: %[[v6:.*]] = "slicing-test-op"(%[[v3]], %[[v4]]) : (i3, i4) -> i6 + // FWDBWD: %[[v7:.*]] = "slicing-test-op"(%[[v1]], %[[v5]]) : (i1, i5) -> i7 + // FWDBWD: %[[v8:.*]] = "slicing-test-op"(%[[v5]], %[[v6]]) : (i5, i6) -> i8 + // FWDBWD: %[[v9:.*]] = "slicing-test-op"(%[[v7]], %[[v8]]) : (i7, i8) -> i9 %9 = "slicing-test-op" (%7, %8) : (i7, i8) -> i9 diff --git a/mlir/test/lib/Analysis/CMakeLists.txt b/mlir/test/lib/Analysis/CMakeLists.txt index d168888c1e71..7c6b31ae8b73 100644 --- a/mlir/test/lib/Analysis/CMakeLists.txt +++ b/mlir/test/lib/Analysis/CMakeLists.txt @@ -10,6 +10,7 @@ add_mlir_library(MLIRTestAnalysis TestMemRefDependenceCheck.cpp TestMemRefStrideCalculation.cpp TestSlice.cpp + TestTopologicalSort.cpp DataFlow/TestDeadCodeAnalysis.cpp DataFlow/TestDenseBackwardDataFlowAnalysis.cpp diff --git a/mlir/test/lib/Analysis/TestSlice.cpp b/mlir/test/lib/Analysis/TestSlice.cpp index b445febde597..7e8320dbf3ec 100644 --- a/mlir/test/lib/Analysis/TestSlice.cpp +++ b/mlir/test/lib/Analysis/TestSlice.cpp @@ -1,4 +1,4 @@ -//===------------- TestSlice.cpp - Test slice related analisis ------------===// +//===- TestSlice.cpp - Test slice related analisis ------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. @@ -6,13 +6,15 @@ // //===----------------------------------------------------------------------===// -#include "mlir/Analysis/SliceAnalysis.h" +#include "mlir/Analysis/TopologicalSortUtils.h" +#include "mlir/IR/BuiltinTypes.h" #include "mlir/IR/SymbolTable.h" #include "mlir/Pass/Pass.h" using namespace mlir; -static const StringLiteral kOrderMarker = "__test_sort_original_idx__"; +static const StringLiteral kToSortMark = "test_to_sort"; +static const StringLiteral kOrderIndex = "test_sort_index"; namespace { @@ -23,23 +25,20 @@ struct TestTopologicalSortPass StringRef getArgument() const final { return "test-print-topological-sort"; } StringRef getDescription() const final { - return "Print operations in topological order"; + return "Sorts operations topologically and attaches attributes with their " + "corresponding index in the ordering to them"; } void runOnOperation() override { - std::map ops; - getOperation().walk([&ops](Operation *op) { - if (auto originalOrderAttr = op->getAttrOfType(kOrderMarker)) - ops[originalOrderAttr.getInt()] = op; + SetVector toSort; + getOperation().walk([&](Operation *op) { + if (op->hasAttrOfType(kToSortMark)) + toSort.insert(op); }); - SetVector sortedOp; - for (auto op : ops) - sortedOp.insert(op.second); - sortedOp = topologicalSort(sortedOp); - llvm::errs() << "Testing : " << getOperation().getName() << "\n"; - for (Operation *op : sortedOp) { - op->print(llvm::errs()); - llvm::errs() << "\n"; - } + + auto i32Type = IntegerType::get(&getContext(), 32); + SetVector sortedOps = topologicalSort(toSort); + for (auto [index, op] : llvm::enumerate(sortedOps)) + op->setAttr(kOrderIndex, IntegerAttr::get(i32Type, index)); } }; diff --git a/mlir/test/lib/Transforms/TestTopologicalSort.cpp b/mlir/test/lib/Analysis/TestTopologicalSort.cpp similarity index 98% rename from mlir/test/lib/Transforms/TestTopologicalSort.cpp rename to mlir/test/lib/Analysis/TestTopologicalSort.cpp index 3b110c712620..c7e0206b2a4d 100644 --- a/mlir/test/lib/Transforms/TestTopologicalSort.cpp +++ b/mlir/test/lib/Analysis/TestTopologicalSort.cpp @@ -6,10 +6,10 @@ // //===----------------------------------------------------------------------===// +#include "mlir/Analysis/TopologicalSortUtils.h" #include "mlir/IR/Builders.h" #include "mlir/IR/BuiltinOps.h" #include "mlir/Pass/Pass.h" -#include "mlir/Transforms/TopologicalSortUtils.h" using namespace mlir; diff --git a/mlir/test/lib/Transforms/CMakeLists.txt b/mlir/test/lib/Transforms/CMakeLists.txt index a849b7ebd29e..975a41ac3d5f 100644 --- a/mlir/test/lib/Transforms/CMakeLists.txt +++ b/mlir/test/lib/Transforms/CMakeLists.txt @@ -26,7 +26,6 @@ add_mlir_library(MLIRTestTransforms TestInlining.cpp TestIntRangeInference.cpp TestMakeIsolatedFromAbove.cpp - TestTopologicalSort.cpp ${MLIRTestTransformsPDLSrc} EXCLUDE_FROM_LIBMLIR diff --git a/utils/bazel/llvm-project-overlay/mlir/BUILD.bazel b/utils/bazel/llvm-project-overlay/mlir/BUILD.bazel index fc449e9010ae..971c851a5f89 100644 --- a/utils/bazel/llvm-project-overlay/mlir/BUILD.bazel +++ b/utils/bazel/llvm-project-overlay/mlir/BUILD.bazel @@ -7597,7 +7597,6 @@ cc_library( "include/mlir/Transforms/LoopInvariantCodeMotionUtils.h", "include/mlir/Transforms/OneToNTypeConversion.h", "include/mlir/Transforms/RegionUtils.h", - "include/mlir/Transforms/TopologicalSortUtils.h", ], includes = ["include"], deps = [ -- GitLab From 1cf75cc77e1d019613644491fb3f2923d4d29774 Mon Sep 17 00:00:00 2001 From: Nikita Popov Date: Wed, 22 May 2024 08:49:12 +0200 Subject: [PATCH 077/452] Revert "[AMDGPU] Update test results to fix build (#92982)" This reverts commit c769079b1098f6b108544176c0bd8b5bba986f2c. This doesn't fix the build, it breaks it. --- llvm/test/CodeGen/AMDGPU/fp_to_sint.ll | 395 +++--- llvm/test/CodeGen/AMDGPU/fp_to_uint.ll | 395 +++--- llvm/test/CodeGen/AMDGPU/llvm.exp.ll | 1592 ++++++++++++------------ llvm/test/CodeGen/AMDGPU/llvm.exp10.ll | 1592 ++++++++++++------------ llvm/test/CodeGen/AMDGPU/shl.ll | 216 ++-- 5 files changed, 2113 insertions(+), 2077 deletions(-) diff --git a/llvm/test/CodeGen/AMDGPU/fp_to_sint.ll b/llvm/test/CodeGen/AMDGPU/fp_to_sint.ll index 04ef30bd26aa..64063f65e288 100644 --- a/llvm/test/CodeGen/AMDGPU/fp_to_sint.ll +++ b/llvm/test/CodeGen/AMDGPU/fp_to_sint.ll @@ -253,25 +253,25 @@ define amdgpu_kernel void @fp_to_sint_i64 (ptr addrspace(1) %out, float %in) { ; EG-NEXT: ADD_INT * T2.W, PV.W, literal.y, ; EG-NEXT: 8388608(1.175494e-38), -150(nan) ; EG-NEXT: ADD_INT T0.X, T0.W, literal.x, -; EG-NEXT: AND_INT T0.Y, PS, literal.y, -; EG-NEXT: SUB_INT T0.Z, literal.z, T0.W, +; EG-NEXT: SUB_INT T0.Y, literal.y, T0.W, +; EG-NEXT: AND_INT T0.Z, PS, literal.z, ; EG-NEXT: NOT_INT T0.W, PS, ; EG-NEXT: LSHR * T3.W, PV.W, 1, -; EG-NEXT: -127(nan), 31(4.344025e-44) -; EG-NEXT: 150(2.101948e-43), 0(0.000000e+00) +; EG-NEXT: -127(nan), 150(2.101948e-43) +; EG-NEXT: 31(4.344025e-44), 0(0.000000e+00) ; EG-NEXT: BIT_ALIGN_INT T1.X, 0.0, PS, PV.W, -; EG-NEXT: AND_INT T1.Y, PV.Z, literal.x, -; EG-NEXT: BIT_ALIGN_INT T0.Z, 0.0, T1.W, PV.Z, -; EG-NEXT: LSHL T0.W, T1.W, PV.Y, -; EG-NEXT: AND_INT * T1.W, T2.W, literal.x, +; EG-NEXT: LSHL T1.Y, T1.W, PV.Z, +; EG-NEXT: AND_INT T0.Z, T2.W, literal.x, BS:VEC_120/SCL_212 +; EG-NEXT: BIT_ALIGN_INT T0.W, 0.0, T1.W, PV.Y, BS:VEC_021/SCL_122 +; EG-NEXT: AND_INT * T1.W, PV.Y, literal.x, ; EG-NEXT: 32(4.484155e-44), 0(0.000000e+00) ; EG-NEXT: CNDE_INT T0.Y, PS, PV.W, 0.0, -; EG-NEXT: CNDE_INT T0.Z, PV.Y, PV.Z, 0.0, -; EG-NEXT: CNDE_INT T0.W, PS, PV.X, PV.W, +; EG-NEXT: CNDE_INT T1.Z, PV.Z, PV.Y, 0.0, +; EG-NEXT: CNDE_INT T0.W, PV.Z, PV.X, PV.Y, ; EG-NEXT: SETGT_INT * T1.W, T0.X, literal.x, ; EG-NEXT: 23(3.222986e-44), 0(0.000000e+00) -; EG-NEXT: CNDE_INT T1.Z, PS, 0.0, PV.W, -; EG-NEXT: CNDE_INT T0.W, PS, PV.Z, PV.Y, +; EG-NEXT: CNDE_INT T0.Z, PS, 0.0, PV.W, +; EG-NEXT: CNDE_INT T0.W, PS, PV.Y, PV.Z, ; EG-NEXT: ASHR * T1.W, KC0[2].Z, literal.x, ; EG-NEXT: 31(4.344025e-44), 0(0.000000e+00) ; EG-NEXT: XOR_INT T0.W, PV.W, PS, @@ -364,78 +364,79 @@ define amdgpu_kernel void @fp_to_sint_v2i64(ptr addrspace(1) %out, <2 x float> % ; ; EG-LABEL: fp_to_sint_v2i64: ; EG: ; %bb.0: -; EG-NEXT: ALU 74, @4, KC0[CB0:0-32], KC1[] +; EG-NEXT: ALU 75, @4, KC0[CB0:0-32], KC1[] ; EG-NEXT: MEM_RAT_CACHELESS STORE_RAW T1.XYZW, T0.X, 1 ; EG-NEXT: CF_END ; EG-NEXT: PAD ; EG-NEXT: ALU clause starting at 4: ; EG-NEXT: MOV * T0.W, literal.x, ; EG-NEXT: 8(1.121039e-44), 0(0.000000e+00) -; EG-NEXT: BFE_UINT T0.Z, KC0[3].X, literal.x, PV.W, -; EG-NEXT: BFE_UINT T0.W, KC0[2].W, literal.x, PV.W, -; EG-NEXT: AND_INT * T1.Z, KC0[2].W, literal.y, -; EG-NEXT: 23(3.222986e-44), 8388607(1.175494e-38) -; EG-NEXT: ADD_INT T1.W, PV.W, literal.x, -; EG-NEXT: ADD_INT * T2.W, PV.Z, literal.x, +; EG-NEXT: BFE_UINT * T1.W, KC0[2].W, literal.x, PV.W, +; EG-NEXT: 23(3.222986e-44), 0(0.000000e+00) +; EG-NEXT: AND_INT T0.Z, KC0[2].W, literal.x, +; EG-NEXT: BFE_UINT T0.W, KC0[3].X, literal.y, T0.W, +; EG-NEXT: ADD_INT * T2.W, PV.W, literal.z, +; EG-NEXT: 8388607(1.175494e-38), 23(3.222986e-44) ; EG-NEXT: -150(nan), 0(0.000000e+00) -; EG-NEXT: AND_INT T0.X, PS, literal.x, -; EG-NEXT: AND_INT T0.Y, PV.W, literal.x, -; EG-NEXT: OR_INT T1.Z, T1.Z, literal.y, -; EG-NEXT: SUB_INT T3.W, literal.z, T0.W, +; EG-NEXT: SUB_INT T0.X, literal.x, PV.W, +; EG-NEXT: SUB_INT T0.Y, literal.x, T1.W, +; EG-NEXT: AND_INT T1.Z, PS, literal.y, +; EG-NEXT: OR_INT T3.W, PV.Z, literal.z, ; EG-NEXT: AND_INT * T4.W, KC0[3].X, literal.w, -; EG-NEXT: 31(4.344025e-44), 8388608(1.175494e-38) -; EG-NEXT: 150(2.101948e-43), 8388607(1.175494e-38) +; EG-NEXT: 150(2.101948e-43), 31(4.344025e-44) +; EG-NEXT: 8388608(1.175494e-38), 8388607(1.175494e-38) ; EG-NEXT: OR_INT T1.X, PS, literal.x, -; EG-NEXT: AND_INT T1.Y, PV.W, literal.y, -; EG-NEXT: BIT_ALIGN_INT T2.Z, 0.0, PV.Z, PV.W, -; EG-NEXT: LSHL T3.W, PV.Z, PV.Y, -; EG-NEXT: AND_INT * T4.W, T1.W, literal.y, +; EG-NEXT: LSHL T1.Y, PV.W, PV.Z, +; EG-NEXT: AND_INT T0.Z, T2.W, literal.y, +; EG-NEXT: BIT_ALIGN_INT T4.W, 0.0, PV.W, PV.Y, +; EG-NEXT: AND_INT * T5.W, PV.Y, literal.y, ; EG-NEXT: 8388608(1.175494e-38), 32(4.484155e-44) -; EG-NEXT: CNDE_INT T0.Y, PS, PV.W, 0.0, -; EG-NEXT: CNDE_INT T2.Z, PV.Y, PV.Z, 0.0, -; EG-NEXT: LSHL T5.W, PV.X, T0.X, -; EG-NEXT: AND_INT * T6.W, T2.W, literal.x, -; EG-NEXT: 32(4.484155e-44), 0(0.000000e+00) +; EG-NEXT: CNDE_INT T2.X, PS, PV.W, 0.0, +; EG-NEXT: CNDE_INT T0.Y, PV.Z, PV.Y, 0.0, +; EG-NEXT: ADD_INT T1.Z, T0.W, literal.x, +; EG-NEXT: BIT_ALIGN_INT T4.W, 0.0, PV.X, T0.X, +; EG-NEXT: AND_INT * T5.W, T0.X, literal.y, +; EG-NEXT: -150(nan), 32(4.484155e-44) ; EG-NEXT: CNDE_INT T0.X, PS, PV.W, 0.0, -; EG-NEXT: NOT_INT T1.Y, T1.W, -; EG-NEXT: SUB_INT T3.Z, literal.x, T0.Z, -; EG-NEXT: NOT_INT T1.W, T2.W, BS:VEC_120/SCL_212 -; EG-NEXT: LSHR * T2.W, T1.X, 1, -; EG-NEXT: 150(2.101948e-43), 0(0.000000e+00) -; EG-NEXT: LSHR T2.X, T1.Z, 1, -; EG-NEXT: ADD_INT T2.Y, T0.Z, literal.x, BS:VEC_120/SCL_212 -; EG-NEXT: BIT_ALIGN_INT T0.Z, 0.0, PS, PV.W, -; EG-NEXT: BIT_ALIGN_INT T1.W, 0.0, T1.X, PV.Z, -; EG-NEXT: AND_INT * T2.W, PV.Z, literal.y, +; EG-NEXT: NOT_INT T2.Y, T2.W, +; EG-NEXT: AND_INT T2.Z, PV.Z, literal.x, +; EG-NEXT: NOT_INT T2.W, PV.Z, +; EG-NEXT: LSHR * T4.W, T1.X, 1, +; EG-NEXT: 31(4.344025e-44), 0(0.000000e+00) +; EG-NEXT: LSHR T3.X, T3.W, 1, +; EG-NEXT: ADD_INT T3.Y, T0.W, literal.x, BS:VEC_120/SCL_212 +; EG-NEXT: BIT_ALIGN_INT T3.Z, 0.0, PS, PV.W, +; EG-NEXT: LSHL T0.W, T1.X, PV.Z, +; EG-NEXT: AND_INT * T2.W, T1.Z, literal.y, ; EG-NEXT: -127(nan), 32(4.484155e-44) ; EG-NEXT: CNDE_INT T1.X, PS, PV.W, 0.0, -; EG-NEXT: CNDE_INT T3.Y, T6.W, PV.Z, T5.W, BS:VEC_021/SCL_122 -; EG-NEXT: SETGT_INT T0.Z, PV.Y, literal.x, -; EG-NEXT: BIT_ALIGN_INT T1.W, 0.0, PV.X, T1.Y, -; EG-NEXT: ADD_INT * T0.W, T0.W, literal.y, +; EG-NEXT: CNDE_INT T4.Y, PS, PV.Z, PV.W, +; EG-NEXT: SETGT_INT T1.Z, PV.Y, literal.x, +; EG-NEXT: BIT_ALIGN_INT T0.W, 0.0, PV.X, T2.Y, +; EG-NEXT: ADD_INT * T1.W, T1.W, literal.y, ; EG-NEXT: 23(3.222986e-44), -127(nan) -; EG-NEXT: CNDE_INT T2.X, T4.W, PV.W, T3.W, +; EG-NEXT: CNDE_INT T3.X, T0.Z, PV.W, T1.Y, ; EG-NEXT: SETGT_INT T1.Y, PS, literal.x, -; EG-NEXT: CNDE_INT T1.Z, PV.Z, 0.0, PV.Y, -; EG-NEXT: CNDE_INT T1.W, PV.Z, PV.X, T0.X, +; EG-NEXT: CNDE_INT T0.Z, PV.Z, 0.0, PV.Y, +; EG-NEXT: CNDE_INT T0.W, PV.Z, T0.X, PV.X, ; EG-NEXT: ASHR * T2.W, KC0[3].X, literal.y, ; EG-NEXT: 23(3.222986e-44), 31(4.344025e-44) ; EG-NEXT: XOR_INT T0.X, PV.W, PS, -; EG-NEXT: XOR_INT T3.Y, PV.Z, PS, +; EG-NEXT: XOR_INT T2.Y, PV.Z, PS, ; EG-NEXT: CNDE_INT T0.Z, PV.Y, 0.0, PV.X, -; EG-NEXT: CNDE_INT T1.W, PV.Y, T2.Z, T0.Y, +; EG-NEXT: CNDE_INT T0.W, PV.Y, T2.X, T0.Y, ; EG-NEXT: ASHR * T3.W, KC0[2].W, literal.x, ; EG-NEXT: 31(4.344025e-44), 0(0.000000e+00) ; EG-NEXT: XOR_INT T0.Y, PV.W, PS, ; EG-NEXT: XOR_INT T0.Z, PV.Z, PS, -; EG-NEXT: SUB_INT T1.W, PV.Y, T2.W, +; EG-NEXT: SUB_INT T0.W, PV.Y, T2.W, ; EG-NEXT: SUBB_UINT * T4.W, PV.X, T2.W, ; EG-NEXT: SUB_INT T1.Y, PV.W, PS, -; EG-NEXT: SETGT_INT T1.Z, 0.0, T2.Y, -; EG-NEXT: SUB_INT T1.W, PV.Z, T3.W, +; EG-NEXT: SETGT_INT T1.Z, 0.0, T3.Y, +; EG-NEXT: SUB_INT T0.W, PV.Z, T3.W, ; EG-NEXT: SUBB_UINT * T4.W, PV.Y, T3.W, ; EG-NEXT: SUB_INT T0.Z, PV.W, PS, -; EG-NEXT: SETGT_INT T0.W, 0.0, T0.W, +; EG-NEXT: SETGT_INT T0.W, 0.0, T1.W, ; EG-NEXT: CNDE_INT * T1.W, PV.Z, PV.Y, 0.0, ; EG-NEXT: CNDE_INT T1.Y, PV.W, PV.Z, 0.0, ; EG-NEXT: SUB_INT * T2.W, T0.X, T2.W, @@ -566,168 +567,170 @@ define amdgpu_kernel void @fp_to_sint_v4i64(ptr addrspace(1) %out, <4 x float> % ; ; EG-LABEL: fp_to_sint_v4i64: ; EG: ; %bb.0: -; EG-NEXT: ALU 99, @6, KC0[CB0:0-32], KC1[] -; EG-NEXT: ALU 54, @106, KC0[CB0:0-32], KC1[] -; EG-NEXT: MEM_RAT_CACHELESS STORE_RAW T1.XYZW, T2.X, 0 -; EG-NEXT: MEM_RAT_CACHELESS STORE_RAW T6.XYZW, T0.X, 1 +; EG-NEXT: ALU 101, @6, KC0[CB0:0-32], KC1[] +; EG-NEXT: ALU 54, @108, KC0[CB0:0-32], KC1[] +; EG-NEXT: MEM_RAT_CACHELESS STORE_RAW T4.XYZW, T0.X, 0 +; EG-NEXT: MEM_RAT_CACHELESS STORE_RAW T6.XYZW, T2.X, 1 ; EG-NEXT: CF_END ; EG-NEXT: PAD ; EG-NEXT: ALU clause starting at 6: ; EG-NEXT: MOV * T0.W, literal.x, ; EG-NEXT: 8(1.121039e-44), 0(0.000000e+00) -; EG-NEXT: BFE_UINT T1.W, KC0[3].Z, literal.x, PV.W, -; EG-NEXT: AND_INT * T2.W, KC0[3].Z, literal.y, +; EG-NEXT: BFE_UINT T1.W, KC0[4].X, literal.x, PV.W, +; EG-NEXT: AND_INT * T2.W, KC0[4].X, literal.y, ; EG-NEXT: 23(3.222986e-44), 8388607(1.175494e-38) -; EG-NEXT: OR_INT T2.W, PS, literal.x, -; EG-NEXT: ADD_INT * T3.W, PV.W, literal.y, -; EG-NEXT: 8388608(1.175494e-38), -150(nan) -; EG-NEXT: ADD_INT T0.X, T1.W, literal.x, -; EG-NEXT: BFE_UINT T0.Y, KC0[4].X, literal.y, T0.W, -; EG-NEXT: AND_INT T0.Z, PS, literal.z, +; EG-NEXT: OR_INT T0.Z, PS, literal.x, +; EG-NEXT: BFE_UINT T2.W, KC0[3].Z, literal.y, T0.W, +; EG-NEXT: ADD_INT * T3.W, PV.W, literal.z, +; EG-NEXT: 8388608(1.175494e-38), 23(3.222986e-44) +; EG-NEXT: -150(nan), 0(0.000000e+00) +; EG-NEXT: ADD_INT T0.Y, PV.W, literal.x, +; EG-NEXT: AND_INT T1.Z, PS, literal.y, ; EG-NEXT: NOT_INT T4.W, PS, -; EG-NEXT: LSHR * T5.W, PV.W, 1, -; EG-NEXT: -127(nan), 23(3.222986e-44) -; EG-NEXT: 31(4.344025e-44), 0(0.000000e+00) -; EG-NEXT: BIT_ALIGN_INT T1.X, 0.0, PS, PV.W, -; EG-NEXT: AND_INT T1.Y, T3.W, literal.x, -; EG-NEXT: LSHL T0.Z, T2.W, PV.Z, BS:VEC_120/SCL_212 -; EG-NEXT: AND_INT T3.W, KC0[4].X, literal.y, -; EG-NEXT: ADD_INT * T4.W, PV.Y, literal.z, +; EG-NEXT: LSHR * T5.W, PV.Z, 1, +; EG-NEXT: -127(nan), 31(4.344025e-44) +; EG-NEXT: ADD_INT T0.X, T1.W, literal.x, +; EG-NEXT: BIT_ALIGN_INT T1.Y, 0.0, PS, PV.W, +; EG-NEXT: AND_INT T2.Z, T3.W, literal.y, BS:VEC_201 +; EG-NEXT: LSHL T3.W, T0.Z, PV.Z, +; EG-NEXT: SUB_INT * T1.W, literal.z, T1.W, +; EG-NEXT: -127(nan), 32(4.484155e-44) +; EG-NEXT: 150(2.101948e-43), 0(0.000000e+00) +; EG-NEXT: AND_INT T1.X, PS, literal.x, +; EG-NEXT: BIT_ALIGN_INT T2.Y, 0.0, T0.Z, PS, +; EG-NEXT: AND_INT T0.Z, KC0[3].Z, literal.y, +; EG-NEXT: CNDE_INT T1.W, PV.Z, PV.Y, PV.W, +; EG-NEXT: SETGT_INT * T4.W, PV.X, literal.z, ; EG-NEXT: 32(4.484155e-44), 8388607(1.175494e-38) -; EG-NEXT: -150(nan), 0(0.000000e+00) -; EG-NEXT: AND_INT T2.Y, PS, literal.x, -; EG-NEXT: OR_INT T1.Z, PV.W, literal.y, -; EG-NEXT: CNDE_INT T3.W, PV.Y, PV.X, PV.Z, -; EG-NEXT: SETGT_INT * T5.W, T0.X, literal.z, -; EG-NEXT: 31(4.344025e-44), 8388608(1.175494e-38) ; EG-NEXT: 23(3.222986e-44), 0(0.000000e+00) -; EG-NEXT: CNDE_INT T3.Y, PS, 0.0, PV.W, -; EG-NEXT: SUB_INT T2.Z, literal.x, T1.W, -; EG-NEXT: LSHL T1.W, PV.Z, PV.Y, -; EG-NEXT: AND_INT * T3.W, T4.W, literal.y, -; EG-NEXT: 150(2.101948e-43), 32(4.484155e-44) -; EG-NEXT: CNDE_INT T1.X, PS, PV.W, 0.0, -; EG-NEXT: AND_INT T2.Y, PV.Z, literal.x, -; EG-NEXT: SUB_INT T3.Z, literal.y, T0.Y, -; EG-NEXT: NOT_INT T4.W, T4.W, -; EG-NEXT: LSHR * T6.W, T1.Z, 1, -; EG-NEXT: 32(4.484155e-44), 150(2.101948e-43) -; EG-NEXT: BIT_ALIGN_INT T2.X, 0.0, T2.W, T2.Z, -; EG-NEXT: ADD_INT T0.Y, T0.Y, literal.x, -; EG-NEXT: BIT_ALIGN_INT T2.Z, 0.0, PS, PV.W, -; EG-NEXT: BIT_ALIGN_INT T2.W, 0.0, T1.Z, PV.Z, -; EG-NEXT: AND_INT * T4.W, PV.Z, literal.y, -; EG-NEXT: -127(nan), 32(4.484155e-44) -; EG-NEXT: CNDE_INT T3.X, PS, PV.W, 0.0, -; EG-NEXT: CNDE_INT T4.Y, T3.W, PV.Z, T1.W, -; EG-NEXT: SETGT_INT T1.Z, PV.Y, literal.x, -; EG-NEXT: CNDE_INT T1.W, T1.Y, T0.Z, 0.0, -; EG-NEXT: CNDE_INT * T2.W, T2.Y, PV.X, 0.0, +; EG-NEXT: CNDE_INT T2.X, PS, 0.0, PV.W, +; EG-NEXT: OR_INT T1.Y, PV.Z, literal.x, +; EG-NEXT: ADD_INT T0.Z, T2.W, literal.y, +; EG-NEXT: CNDE_INT T1.W, PV.X, PV.Y, 0.0, +; EG-NEXT: CNDE_INT * T3.W, T2.Z, T3.W, 0.0, +; EG-NEXT: 8388608(1.175494e-38), -150(nan) +; EG-NEXT: CNDE_INT T1.X, T4.W, PV.W, PS, +; EG-NEXT: ASHR T2.Y, KC0[4].X, literal.x, +; EG-NEXT: AND_INT T1.Z, PV.Z, literal.x, +; EG-NEXT: NOT_INT T1.W, PV.Z, +; EG-NEXT: LSHR * T3.W, PV.Y, 1, +; EG-NEXT: 31(4.344025e-44), 0(0.000000e+00) +; EG-NEXT: BIT_ALIGN_INT T3.X, 0.0, PS, PV.W, +; EG-NEXT: LSHL T3.Y, T1.Y, PV.Z, +; EG-NEXT: XOR_INT T1.Z, PV.X, PV.Y, +; EG-NEXT: XOR_INT T1.W, T2.X, PV.Y, +; EG-NEXT: SUB_INT * T2.W, literal.x, T2.W, +; EG-NEXT: 150(2.101948e-43), 0(0.000000e+00) +; EG-NEXT: AND_INT T1.X, T0.Z, literal.x, +; EG-NEXT: AND_INT T4.Y, PS, literal.x, +; EG-NEXT: BIT_ALIGN_INT T0.Z, 0.0, T1.Y, PS, BS:VEC_021/SCL_122 +; EG-NEXT: SUB_INT T1.W, PV.W, T2.Y, +; EG-NEXT: SUBB_UINT * T2.W, PV.Z, T2.Y, +; EG-NEXT: 32(4.484155e-44), 0(0.000000e+00) +; EG-NEXT: SUB_INT T2.X, PV.W, PS, +; EG-NEXT: CNDE_INT T1.Y, PV.Y, PV.Z, 0.0, +; EG-NEXT: CNDE_INT T0.Z, PV.X, T3.Y, 0.0, +; EG-NEXT: CNDE_INT T1.W, PV.X, T3.X, T3.Y, BS:VEC_021/SCL_122 +; EG-NEXT: SETGT_INT * T2.W, T0.Y, literal.x, ; EG-NEXT: 23(3.222986e-44), 0(0.000000e+00) -; EG-NEXT: CNDE_INT T2.X, T5.W, PS, PV.W, -; EG-NEXT: ASHR T1.Y, KC0[3].Z, literal.x, -; EG-NEXT: CNDE_INT T0.Z, PV.Z, 0.0, PV.Y, -; EG-NEXT: CNDE_INT T1.W, PV.Z, PV.X, T1.X, -; EG-NEXT: ASHR * T2.W, KC0[4].X, literal.x, +; EG-NEXT: BFE_UINT T1.X, KC0[3].W, literal.x, T0.W, +; EG-NEXT: AND_INT T3.Y, KC0[3].W, literal.y, +; EG-NEXT: CNDE_INT T2.Z, PS, 0.0, PV.W, +; EG-NEXT: CNDE_INT T1.W, PS, PV.Y, PV.Z, +; EG-NEXT: ASHR * T2.W, KC0[3].Z, literal.z, +; EG-NEXT: 23(3.222986e-44), 8388607(1.175494e-38) ; EG-NEXT: 31(4.344025e-44), 0(0.000000e+00) -; EG-NEXT: XOR_INT T2.Y, PV.W, PS, +; EG-NEXT: BFE_UINT T3.X, KC0[3].Y, literal.x, T0.W, +; EG-NEXT: XOR_INT T1.Y, PV.W, PS, ; EG-NEXT: XOR_INT T0.Z, PV.Z, PS, -; EG-NEXT: XOR_INT T1.W, PV.X, PV.Y, -; EG-NEXT: XOR_INT * T3.W, T3.Y, PV.Y, -; EG-NEXT: SUB_INT T3.Y, PS, T1.Y, -; EG-NEXT: SUBB_UINT T1.Z, PV.W, T1.Y, -; EG-NEXT: SUB_INT T3.W, PV.Z, T2.W, -; EG-NEXT: SUBB_UINT * T4.W, PV.Y, T2.W, -; EG-NEXT: SUB_INT T4.Y, PV.W, PS, -; EG-NEXT: SUB_INT T0.Z, PV.Y, PV.Z, -; EG-NEXT: BFE_UINT T3.W, KC0[3].Y, literal.x, T0.W, -; EG-NEXT: AND_INT * T4.W, KC0[3].Y, literal.y, -; EG-NEXT: 23(3.222986e-44), 8388607(1.175494e-38) -; EG-NEXT: SETGT_INT T0.X, 0.0, T0.X, -; EG-NEXT: ADD_INT T3.Y, PV.W, literal.x, -; EG-NEXT: OR_INT T1.Z, PS, literal.y, -; EG-NEXT: BFE_UINT T0.W, KC0[3].W, literal.z, T0.W, -; EG-NEXT: ADD_INT * T4.W, PV.W, literal.w, -; EG-NEXT: -127(nan), 8388608(1.175494e-38) -; EG-NEXT: 23(3.222986e-44), -150(nan) -; EG-NEXT: AND_INT T1.X, KC0[3].W, literal.x, -; EG-NEXT: ADD_INT T5.Y, PV.W, literal.y, -; EG-NEXT: SUB_INT T2.Z, literal.z, T3.W, -; EG-NEXT: NOT_INT T3.W, PS, -; EG-NEXT: LSHR * T5.W, PV.Z, 1, -; EG-NEXT: 8388607(1.175494e-38), -150(nan) +; EG-NEXT: OR_INT T0.W, PV.Y, literal.y, +; EG-NEXT: SUB_INT * T1.W, literal.z, PV.X, +; EG-NEXT: 23(3.222986e-44), 8388608(1.175494e-38) ; EG-NEXT: 150(2.101948e-43), 0(0.000000e+00) -; EG-NEXT: BIT_ALIGN_INT T2.X, 0.0, PS, PV.W, -; EG-NEXT: AND_INT T6.Y, PV.Z, literal.x, -; EG-NEXT: AND_INT T3.Z, PV.Y, literal.y, -; EG-NEXT: OR_INT T3.W, PV.X, literal.z, -; EG-NEXT: AND_INT * T5.W, T4.W, literal.y, -; EG-NEXT: 32(4.484155e-44), 31(4.344025e-44) -; EG-NEXT: 8388608(1.175494e-38), 0(0.000000e+00) -; EG-NEXT: BIT_ALIGN_INT T1.X, 0.0, T1.Z, T2.Z, -; EG-NEXT: LSHL T7.Y, T1.Z, PS, -; EG-NEXT: AND_INT T1.Z, T4.W, literal.x, -; EG-NEXT: LSHL T4.W, PV.W, PV.Z, -; EG-NEXT: AND_INT * T5.W, T5.Y, literal.x, +; EG-NEXT: AND_INT T4.X, KC0[3].Y, literal.x, +; EG-NEXT: AND_INT T3.Y, PS, literal.y, +; EG-NEXT: BIT_ALIGN_INT T2.Z, 0.0, PV.W, PS, +; EG-NEXT: SUB_INT T1.W, PV.Z, T2.W, +; EG-NEXT: SUBB_UINT * T3.W, PV.Y, T2.W, +; EG-NEXT: 8388607(1.175494e-38), 32(4.484155e-44) +; EG-NEXT: SUB_INT T5.X, PV.W, PS, +; EG-NEXT: SETGT_INT T0.Y, 0.0, T0.Y, +; EG-NEXT: CNDE_INT T0.Z, PV.Y, PV.Z, 0.0, +; EG-NEXT: OR_INT T1.W, PV.X, literal.x, +; EG-NEXT: ADD_INT * T3.W, T3.X, literal.y, +; EG-NEXT: 8388608(1.175494e-38), -150(nan) +; EG-NEXT: ADD_INT T4.X, T3.X, literal.x, +; EG-NEXT: SUB_INT T3.Y, literal.y, T3.X, +; EG-NEXT: AND_INT T2.Z, PS, literal.z, +; EG-NEXT: NOT_INT T4.W, PS, +; EG-NEXT: LSHR * T5.W, PV.W, 1, +; EG-NEXT: -127(nan), 150(2.101948e-43) +; EG-NEXT: 31(4.344025e-44), 0(0.000000e+00) +; EG-NEXT: BIT_ALIGN_INT T3.X, 0.0, PS, PV.W, +; EG-NEXT: LSHL T4.Y, T1.W, PV.Z, +; EG-NEXT: AND_INT T2.Z, T3.W, literal.x, BS:VEC_120/SCL_212 +; EG-NEXT: BIT_ALIGN_INT T1.W, 0.0, T1.W, PV.Y, BS:VEC_021/SCL_122 +; EG-NEXT: AND_INT * T3.W, PV.Y, literal.x, ; EG-NEXT: 32(4.484155e-44), 0(0.000000e+00) -; EG-NEXT: CNDE_INT T3.X, PS, PV.W, 0.0, -; EG-NEXT: CNDE_INT T8.Y, PV.Z, PV.Y, 0.0, -; EG-NEXT: CNDE_INT * T2.Z, T6.Y, PV.X, 0.0, -; EG-NEXT: ALU clause starting at 106: -; EG-NEXT: CNDE_INT T6.W, T1.Z, T2.X, T7.Y, BS:VEC_021/SCL_122 -; EG-NEXT: SETGT_INT * T7.W, T3.Y, literal.x, +; EG-NEXT: ADD_INT T6.X, T1.X, literal.x, +; EG-NEXT: CNDE_INT T3.Y, PS, PV.W, 0.0, +; EG-NEXT: CNDE_INT * T3.Z, PV.Z, PV.Y, 0.0, +; EG-NEXT: -150(nan), 0(0.000000e+00) +; EG-NEXT: ALU clause starting at 108: +; EG-NEXT: CNDE_INT T1.W, T2.Z, T3.X, T4.Y, +; EG-NEXT: SETGT_INT * T3.W, T4.X, literal.x, ; EG-NEXT: 23(3.222986e-44), 0(0.000000e+00) -; EG-NEXT: CNDE_INT T1.X, PS, 0.0, PV.W, -; EG-NEXT: CNDE_INT T6.Y, PS, T2.Z, T8.Y, -; EG-NEXT: SUB_INT T1.Z, literal.x, T0.W, -; EG-NEXT: NOT_INT T6.W, T5.Y, -; EG-NEXT: LSHR * T7.W, T3.W, 1, -; EG-NEXT: 150(2.101948e-43), 0(0.000000e+00) -; EG-NEXT: ASHR T2.X, KC0[3].Y, literal.x, -; EG-NEXT: ADD_INT T5.Y, T0.W, literal.y, -; EG-NEXT: BIT_ALIGN_INT T2.Z, 0.0, PS, PV.W, -; EG-NEXT: BIT_ALIGN_INT T0.W, 0.0, T3.W, PV.Z, -; EG-NEXT: AND_INT * T3.W, PV.Z, literal.z, +; EG-NEXT: CNDE_INT T3.X, PS, 0.0, PV.W, +; EG-NEXT: CNDE_INT T3.Y, PS, T3.Y, T3.Z, +; EG-NEXT: AND_INT T2.Z, T6.X, literal.x, +; EG-NEXT: NOT_INT T1.W, T6.X, +; EG-NEXT: LSHR * T3.W, T0.W, 1, +; EG-NEXT: 31(4.344025e-44), 0(0.000000e+00) +; EG-NEXT: ASHR T7.X, KC0[3].Y, literal.x, +; EG-NEXT: ADD_INT T4.Y, T1.X, literal.y, +; EG-NEXT: BIT_ALIGN_INT T3.Z, 0.0, PS, PV.W, +; EG-NEXT: LSHL T0.W, T0.W, PV.Z, +; EG-NEXT: AND_INT * T1.W, T6.X, literal.z, ; EG-NEXT: 31(4.344025e-44), -127(nan) ; EG-NEXT: 32(4.484155e-44), 0(0.000000e+00) -; EG-NEXT: CNDE_INT T4.X, PS, PV.W, 0.0, -; EG-NEXT: CNDE_INT T7.Y, T5.W, PV.Z, T4.W, -; EG-NEXT: SETGT_INT T1.Z, PV.Y, literal.x, -; EG-NEXT: XOR_INT T0.W, T6.Y, PV.X, -; EG-NEXT: XOR_INT * T3.W, T1.X, PV.X, +; EG-NEXT: CNDE_INT T1.X, PS, PV.W, 0.0, +; EG-NEXT: CNDE_INT T5.Y, PS, PV.Z, PV.W, +; EG-NEXT: SETGT_INT T2.Z, PV.Y, literal.x, +; EG-NEXT: XOR_INT T0.W, T3.Y, PV.X, +; EG-NEXT: XOR_INT * T1.W, T3.X, PV.X, ; EG-NEXT: 23(3.222986e-44), 0(0.000000e+00) -; EG-NEXT: SUB_INT T1.X, PS, T2.X, -; EG-NEXT: SUBB_UINT T6.Y, PV.W, T2.X, -; EG-NEXT: CNDE_INT T2.Z, PV.Z, 0.0, PV.Y, -; EG-NEXT: CNDE_INT T3.W, PV.Z, PV.X, T3.X, -; EG-NEXT: ASHR * T4.W, KC0[3].W, literal.x, +; EG-NEXT: SUB_INT T3.X, PS, T7.X, +; EG-NEXT: SUBB_UINT T3.Y, PV.W, T7.X, +; EG-NEXT: CNDE_INT T3.Z, PV.Z, 0.0, PV.Y, +; EG-NEXT: CNDE_INT T1.W, PV.Z, T0.Z, PV.X, +; EG-NEXT: ASHR * T3.W, KC0[3].W, literal.x, ; EG-NEXT: 31(4.344025e-44), 0(0.000000e+00) -; EG-NEXT: XOR_INT T3.X, PV.W, PS, -; EG-NEXT: XOR_INT T7.Y, PV.Z, PS, -; EG-NEXT: SUB_INT T1.Z, PV.X, PV.Y, -; EG-NEXT: SETGT_INT T3.W, 0.0, T3.Y, -; EG-NEXT: CNDE_INT * T6.W, T0.X, T0.Z, 0.0, -; EG-NEXT: SETGT_INT T1.X, 0.0, T0.Y, +; EG-NEXT: XOR_INT T1.X, PV.W, PS, +; EG-NEXT: XOR_INT T5.Y, PV.Z, PS, +; EG-NEXT: SUB_INT T0.Z, PV.X, PV.Y, +; EG-NEXT: SETGT_INT T1.W, 0.0, T4.X, BS:VEC_021/SCL_122 +; EG-NEXT: CNDE_INT * T6.W, T0.Y, T5.X, 0.0, +; EG-NEXT: SETGT_INT T0.X, 0.0, T0.X, ; EG-NEXT: CNDE_INT T6.Y, PV.W, PV.Z, 0.0, -; EG-NEXT: SUB_INT T0.Z, T1.W, T1.Y, BS:VEC_021/SCL_122 -; EG-NEXT: SUB_INT T1.W, PV.Y, T4.W, -; EG-NEXT: SUBB_UINT * T5.W, PV.X, T4.W, -; EG-NEXT: SUB_INT T4.X, PV.W, PS, -; EG-NEXT: SETGT_INT T0.Y, 0.0, T5.Y, BS:VEC_021/SCL_122 -; EG-NEXT: CNDE_INT T6.Z, T0.X, PV.Z, 0.0, -; EG-NEXT: SUB_INT T0.W, T0.W, T2.X, -; EG-NEXT: CNDE_INT * T1.W, PV.X, T4.Y, 0.0, -; EG-NEXT: CNDE_INT T6.X, T3.W, PV.W, 0.0, -; EG-NEXT: CNDE_INT T1.Y, PV.Y, PV.X, 0.0, -; EG-NEXT: SUB_INT T0.W, T2.Y, T2.W, -; EG-NEXT: LSHR * T0.X, KC0[2].Y, literal.x, +; EG-NEXT: SUB_INT T0.Z, T1.Y, T2.W, BS:VEC_021/SCL_122 +; EG-NEXT: SUB_INT T2.W, PV.Y, T3.W, +; EG-NEXT: SUBB_UINT * T4.W, PV.X, T3.W, +; EG-NEXT: SUB_INT T3.X, PV.W, PS, +; EG-NEXT: SETGT_INT T1.Y, 0.0, T4.Y, +; EG-NEXT: CNDE_INT T6.Z, T0.Y, PV.Z, 0.0, +; EG-NEXT: SUB_INT T0.W, T0.W, T7.X, BS:VEC_021/SCL_122 +; EG-NEXT: CNDE_INT * T4.W, PV.X, T2.X, 0.0, +; EG-NEXT: CNDE_INT T6.X, T1.W, PV.W, 0.0, +; EG-NEXT: CNDE_INT T4.Y, PV.Y, PV.X, 0.0, +; EG-NEXT: SUB_INT T0.W, T1.Z, T2.Y, +; EG-NEXT: LSHR * T2.X, KC0[2].Y, literal.x, ; EG-NEXT: 2(2.802597e-45), 0(0.000000e+00) -; EG-NEXT: CNDE_INT T1.Z, T1.X, PV.W, 0.0, -; EG-NEXT: SUB_INT * T0.W, T3.X, T4.W, BS:VEC_120/SCL_212 -; EG-NEXT: CNDE_INT T1.X, T0.Y, PV.W, 0.0, +; EG-NEXT: CNDE_INT T4.Z, T0.X, PV.W, 0.0, +; EG-NEXT: SUB_INT * T0.W, T1.X, T3.W, BS:VEC_120/SCL_212 +; EG-NEXT: CNDE_INT T4.X, T1.Y, PV.W, 0.0, ; EG-NEXT: ADD_INT * T0.W, KC0[2].Y, literal.x, ; EG-NEXT: 16(2.242078e-44), 0(0.000000e+00) -; EG-NEXT: LSHR * T2.X, PV.W, literal.x, +; EG-NEXT: LSHR * T0.X, PV.W, literal.x, ; EG-NEXT: 2(2.802597e-45), 0(0.000000e+00) %conv = fptosi <4 x float> %x to <4 x i64> store <4 x i64> %conv, ptr addrspace(1) %out diff --git a/llvm/test/CodeGen/AMDGPU/fp_to_uint.ll b/llvm/test/CodeGen/AMDGPU/fp_to_uint.ll index 5abf82aa1aab..5170f9c76db2 100644 --- a/llvm/test/CodeGen/AMDGPU/fp_to_uint.ll +++ b/llvm/test/CodeGen/AMDGPU/fp_to_uint.ll @@ -200,25 +200,25 @@ define amdgpu_kernel void @fp_to_uint_f32_to_i64(ptr addrspace(1) %out, float %x ; EG-NEXT: ADD_INT * T2.W, PV.W, literal.y, ; EG-NEXT: 8388608(1.175494e-38), -150(nan) ; EG-NEXT: ADD_INT T0.X, T0.W, literal.x, -; EG-NEXT: AND_INT T0.Y, PS, literal.y, -; EG-NEXT: SUB_INT T0.Z, literal.z, T0.W, +; EG-NEXT: SUB_INT T0.Y, literal.y, T0.W, +; EG-NEXT: AND_INT T0.Z, PS, literal.z, ; EG-NEXT: NOT_INT T0.W, PS, ; EG-NEXT: LSHR * T3.W, PV.W, 1, -; EG-NEXT: -127(nan), 31(4.344025e-44) -; EG-NEXT: 150(2.101948e-43), 0(0.000000e+00) +; EG-NEXT: -127(nan), 150(2.101948e-43) +; EG-NEXT: 31(4.344025e-44), 0(0.000000e+00) ; EG-NEXT: BIT_ALIGN_INT T1.X, 0.0, PS, PV.W, -; EG-NEXT: AND_INT T1.Y, PV.Z, literal.x, -; EG-NEXT: BIT_ALIGN_INT T0.Z, 0.0, T1.W, PV.Z, -; EG-NEXT: LSHL T0.W, T1.W, PV.Y, -; EG-NEXT: AND_INT * T1.W, T2.W, literal.x, +; EG-NEXT: LSHL T1.Y, T1.W, PV.Z, +; EG-NEXT: AND_INT T0.Z, T2.W, literal.x, BS:VEC_120/SCL_212 +; EG-NEXT: BIT_ALIGN_INT T0.W, 0.0, T1.W, PV.Y, BS:VEC_021/SCL_122 +; EG-NEXT: AND_INT * T1.W, PV.Y, literal.x, ; EG-NEXT: 32(4.484155e-44), 0(0.000000e+00) ; EG-NEXT: CNDE_INT T0.Y, PS, PV.W, 0.0, -; EG-NEXT: CNDE_INT T0.Z, PV.Y, PV.Z, 0.0, -; EG-NEXT: CNDE_INT T0.W, PS, PV.X, PV.W, +; EG-NEXT: CNDE_INT T1.Z, PV.Z, PV.Y, 0.0, +; EG-NEXT: CNDE_INT T0.W, PV.Z, PV.X, PV.Y, ; EG-NEXT: SETGT_INT * T1.W, T0.X, literal.x, ; EG-NEXT: 23(3.222986e-44), 0(0.000000e+00) -; EG-NEXT: CNDE_INT T1.Z, PS, 0.0, PV.W, -; EG-NEXT: CNDE_INT T0.W, PS, PV.Z, PV.Y, +; EG-NEXT: CNDE_INT T0.Z, PS, 0.0, PV.W, +; EG-NEXT: CNDE_INT T0.W, PS, PV.Y, PV.Z, ; EG-NEXT: ASHR * T1.W, KC0[2].Z, literal.x, ; EG-NEXT: 31(4.344025e-44), 0(0.000000e+00) ; EG-NEXT: XOR_INT T0.W, PV.W, PS, @@ -288,78 +288,79 @@ define amdgpu_kernel void @fp_to_uint_v2f32_to_v2i64(ptr addrspace(1) %out, <2 x ; ; EG-LABEL: fp_to_uint_v2f32_to_v2i64: ; EG: ; %bb.0: -; EG-NEXT: ALU 74, @4, KC0[CB0:0-32], KC1[] +; EG-NEXT: ALU 75, @4, KC0[CB0:0-32], KC1[] ; EG-NEXT: MEM_RAT_CACHELESS STORE_RAW T1.XYZW, T0.X, 1 ; EG-NEXT: CF_END ; EG-NEXT: PAD ; EG-NEXT: ALU clause starting at 4: ; EG-NEXT: MOV * T0.W, literal.x, ; EG-NEXT: 8(1.121039e-44), 0(0.000000e+00) -; EG-NEXT: BFE_UINT T0.Z, KC0[3].X, literal.x, PV.W, -; EG-NEXT: BFE_UINT T0.W, KC0[2].W, literal.x, PV.W, -; EG-NEXT: AND_INT * T1.Z, KC0[2].W, literal.y, -; EG-NEXT: 23(3.222986e-44), 8388607(1.175494e-38) -; EG-NEXT: ADD_INT T1.W, PV.W, literal.x, -; EG-NEXT: ADD_INT * T2.W, PV.Z, literal.x, +; EG-NEXT: BFE_UINT * T1.W, KC0[2].W, literal.x, PV.W, +; EG-NEXT: 23(3.222986e-44), 0(0.000000e+00) +; EG-NEXT: AND_INT T0.Z, KC0[2].W, literal.x, +; EG-NEXT: BFE_UINT T0.W, KC0[3].X, literal.y, T0.W, +; EG-NEXT: ADD_INT * T2.W, PV.W, literal.z, +; EG-NEXT: 8388607(1.175494e-38), 23(3.222986e-44) ; EG-NEXT: -150(nan), 0(0.000000e+00) -; EG-NEXT: AND_INT T0.X, PS, literal.x, -; EG-NEXT: AND_INT T0.Y, PV.W, literal.x, -; EG-NEXT: OR_INT T1.Z, T1.Z, literal.y, -; EG-NEXT: SUB_INT T3.W, literal.z, T0.W, +; EG-NEXT: SUB_INT T0.X, literal.x, PV.W, +; EG-NEXT: SUB_INT T0.Y, literal.x, T1.W, +; EG-NEXT: AND_INT T1.Z, PS, literal.y, +; EG-NEXT: OR_INT T3.W, PV.Z, literal.z, ; EG-NEXT: AND_INT * T4.W, KC0[3].X, literal.w, -; EG-NEXT: 31(4.344025e-44), 8388608(1.175494e-38) -; EG-NEXT: 150(2.101948e-43), 8388607(1.175494e-38) +; EG-NEXT: 150(2.101948e-43), 31(4.344025e-44) +; EG-NEXT: 8388608(1.175494e-38), 8388607(1.175494e-38) ; EG-NEXT: OR_INT T1.X, PS, literal.x, -; EG-NEXT: AND_INT T1.Y, PV.W, literal.y, -; EG-NEXT: BIT_ALIGN_INT T2.Z, 0.0, PV.Z, PV.W, -; EG-NEXT: LSHL T3.W, PV.Z, PV.Y, -; EG-NEXT: AND_INT * T4.W, T1.W, literal.y, +; EG-NEXT: LSHL T1.Y, PV.W, PV.Z, +; EG-NEXT: AND_INT T0.Z, T2.W, literal.y, +; EG-NEXT: BIT_ALIGN_INT T4.W, 0.0, PV.W, PV.Y, +; EG-NEXT: AND_INT * T5.W, PV.Y, literal.y, ; EG-NEXT: 8388608(1.175494e-38), 32(4.484155e-44) -; EG-NEXT: CNDE_INT T0.Y, PS, PV.W, 0.0, -; EG-NEXT: CNDE_INT T2.Z, PV.Y, PV.Z, 0.0, -; EG-NEXT: LSHL T5.W, PV.X, T0.X, -; EG-NEXT: AND_INT * T6.W, T2.W, literal.x, -; EG-NEXT: 32(4.484155e-44), 0(0.000000e+00) +; EG-NEXT: CNDE_INT T2.X, PS, PV.W, 0.0, +; EG-NEXT: CNDE_INT T0.Y, PV.Z, PV.Y, 0.0, +; EG-NEXT: ADD_INT T1.Z, T0.W, literal.x, +; EG-NEXT: BIT_ALIGN_INT T4.W, 0.0, PV.X, T0.X, +; EG-NEXT: AND_INT * T5.W, T0.X, literal.y, +; EG-NEXT: -150(nan), 32(4.484155e-44) ; EG-NEXT: CNDE_INT T0.X, PS, PV.W, 0.0, -; EG-NEXT: NOT_INT T1.Y, T1.W, -; EG-NEXT: SUB_INT T3.Z, literal.x, T0.Z, -; EG-NEXT: NOT_INT T1.W, T2.W, BS:VEC_120/SCL_212 -; EG-NEXT: LSHR * T2.W, T1.X, 1, -; EG-NEXT: 150(2.101948e-43), 0(0.000000e+00) -; EG-NEXT: LSHR T2.X, T1.Z, 1, -; EG-NEXT: ADD_INT T2.Y, T0.Z, literal.x, BS:VEC_120/SCL_212 -; EG-NEXT: BIT_ALIGN_INT T0.Z, 0.0, PS, PV.W, -; EG-NEXT: BIT_ALIGN_INT T1.W, 0.0, T1.X, PV.Z, -; EG-NEXT: AND_INT * T2.W, PV.Z, literal.y, +; EG-NEXT: NOT_INT T2.Y, T2.W, +; EG-NEXT: AND_INT T2.Z, PV.Z, literal.x, +; EG-NEXT: NOT_INT T2.W, PV.Z, +; EG-NEXT: LSHR * T4.W, T1.X, 1, +; EG-NEXT: 31(4.344025e-44), 0(0.000000e+00) +; EG-NEXT: LSHR T3.X, T3.W, 1, +; EG-NEXT: ADD_INT T3.Y, T0.W, literal.x, BS:VEC_120/SCL_212 +; EG-NEXT: BIT_ALIGN_INT T3.Z, 0.0, PS, PV.W, +; EG-NEXT: LSHL T0.W, T1.X, PV.Z, +; EG-NEXT: AND_INT * T2.W, T1.Z, literal.y, ; EG-NEXT: -127(nan), 32(4.484155e-44) ; EG-NEXT: CNDE_INT T1.X, PS, PV.W, 0.0, -; EG-NEXT: CNDE_INT T3.Y, T6.W, PV.Z, T5.W, BS:VEC_021/SCL_122 -; EG-NEXT: SETGT_INT T0.Z, PV.Y, literal.x, -; EG-NEXT: BIT_ALIGN_INT T1.W, 0.0, PV.X, T1.Y, -; EG-NEXT: ADD_INT * T0.W, T0.W, literal.y, +; EG-NEXT: CNDE_INT T4.Y, PS, PV.Z, PV.W, +; EG-NEXT: SETGT_INT T1.Z, PV.Y, literal.x, +; EG-NEXT: BIT_ALIGN_INT T0.W, 0.0, PV.X, T2.Y, +; EG-NEXT: ADD_INT * T1.W, T1.W, literal.y, ; EG-NEXT: 23(3.222986e-44), -127(nan) -; EG-NEXT: CNDE_INT T2.X, T4.W, PV.W, T3.W, +; EG-NEXT: CNDE_INT T3.X, T0.Z, PV.W, T1.Y, ; EG-NEXT: SETGT_INT T1.Y, PS, literal.x, -; EG-NEXT: CNDE_INT T1.Z, PV.Z, 0.0, PV.Y, -; EG-NEXT: CNDE_INT T1.W, PV.Z, PV.X, T0.X, +; EG-NEXT: CNDE_INT T0.Z, PV.Z, 0.0, PV.Y, +; EG-NEXT: CNDE_INT T0.W, PV.Z, T0.X, PV.X, ; EG-NEXT: ASHR * T2.W, KC0[3].X, literal.y, ; EG-NEXT: 23(3.222986e-44), 31(4.344025e-44) ; EG-NEXT: XOR_INT T0.X, PV.W, PS, -; EG-NEXT: XOR_INT T3.Y, PV.Z, PS, +; EG-NEXT: XOR_INT T2.Y, PV.Z, PS, ; EG-NEXT: CNDE_INT T0.Z, PV.Y, 0.0, PV.X, -; EG-NEXT: CNDE_INT T1.W, PV.Y, T2.Z, T0.Y, +; EG-NEXT: CNDE_INT T0.W, PV.Y, T2.X, T0.Y, ; EG-NEXT: ASHR * T3.W, KC0[2].W, literal.x, ; EG-NEXT: 31(4.344025e-44), 0(0.000000e+00) ; EG-NEXT: XOR_INT T0.Y, PV.W, PS, ; EG-NEXT: XOR_INT T0.Z, PV.Z, PS, -; EG-NEXT: SUB_INT T1.W, PV.Y, T2.W, +; EG-NEXT: SUB_INT T0.W, PV.Y, T2.W, ; EG-NEXT: SUBB_UINT * T4.W, PV.X, T2.W, ; EG-NEXT: SUB_INT T1.Y, PV.W, PS, -; EG-NEXT: SETGT_INT T1.Z, 0.0, T2.Y, -; EG-NEXT: SUB_INT T1.W, PV.Z, T3.W, +; EG-NEXT: SETGT_INT T1.Z, 0.0, T3.Y, +; EG-NEXT: SUB_INT T0.W, PV.Z, T3.W, ; EG-NEXT: SUBB_UINT * T4.W, PV.Y, T3.W, ; EG-NEXT: SUB_INT T0.Z, PV.W, PS, -; EG-NEXT: SETGT_INT T0.W, 0.0, T0.W, +; EG-NEXT: SETGT_INT T0.W, 0.0, T1.W, ; EG-NEXT: CNDE_INT * T1.W, PV.Z, PV.Y, 0.0, ; EG-NEXT: CNDE_INT T1.Y, PV.W, PV.Z, 0.0, ; EG-NEXT: SUB_INT * T2.W, T0.X, T2.W, @@ -448,168 +449,170 @@ define amdgpu_kernel void @fp_to_uint_v4f32_to_v4i64(ptr addrspace(1) %out, <4 x ; ; EG-LABEL: fp_to_uint_v4f32_to_v4i64: ; EG: ; %bb.0: -; EG-NEXT: ALU 99, @6, KC0[CB0:0-32], KC1[] -; EG-NEXT: ALU 54, @106, KC0[CB0:0-32], KC1[] -; EG-NEXT: MEM_RAT_CACHELESS STORE_RAW T1.XYZW, T2.X, 0 -; EG-NEXT: MEM_RAT_CACHELESS STORE_RAW T6.XYZW, T0.X, 1 +; EG-NEXT: ALU 101, @6, KC0[CB0:0-32], KC1[] +; EG-NEXT: ALU 54, @108, KC0[CB0:0-32], KC1[] +; EG-NEXT: MEM_RAT_CACHELESS STORE_RAW T4.XYZW, T0.X, 0 +; EG-NEXT: MEM_RAT_CACHELESS STORE_RAW T6.XYZW, T2.X, 1 ; EG-NEXT: CF_END ; EG-NEXT: PAD ; EG-NEXT: ALU clause starting at 6: ; EG-NEXT: MOV * T0.W, literal.x, ; EG-NEXT: 8(1.121039e-44), 0(0.000000e+00) -; EG-NEXT: BFE_UINT T1.W, KC0[3].Z, literal.x, PV.W, -; EG-NEXT: AND_INT * T2.W, KC0[3].Z, literal.y, +; EG-NEXT: BFE_UINT T1.W, KC0[4].X, literal.x, PV.W, +; EG-NEXT: AND_INT * T2.W, KC0[4].X, literal.y, ; EG-NEXT: 23(3.222986e-44), 8388607(1.175494e-38) -; EG-NEXT: OR_INT T2.W, PS, literal.x, -; EG-NEXT: ADD_INT * T3.W, PV.W, literal.y, -; EG-NEXT: 8388608(1.175494e-38), -150(nan) -; EG-NEXT: ADD_INT T0.X, T1.W, literal.x, -; EG-NEXT: BFE_UINT T0.Y, KC0[4].X, literal.y, T0.W, -; EG-NEXT: AND_INT T0.Z, PS, literal.z, +; EG-NEXT: OR_INT T0.Z, PS, literal.x, +; EG-NEXT: BFE_UINT T2.W, KC0[3].Z, literal.y, T0.W, +; EG-NEXT: ADD_INT * T3.W, PV.W, literal.z, +; EG-NEXT: 8388608(1.175494e-38), 23(3.222986e-44) +; EG-NEXT: -150(nan), 0(0.000000e+00) +; EG-NEXT: ADD_INT T0.Y, PV.W, literal.x, +; EG-NEXT: AND_INT T1.Z, PS, literal.y, ; EG-NEXT: NOT_INT T4.W, PS, -; EG-NEXT: LSHR * T5.W, PV.W, 1, -; EG-NEXT: -127(nan), 23(3.222986e-44) -; EG-NEXT: 31(4.344025e-44), 0(0.000000e+00) -; EG-NEXT: BIT_ALIGN_INT T1.X, 0.0, PS, PV.W, -; EG-NEXT: AND_INT T1.Y, T3.W, literal.x, -; EG-NEXT: LSHL T0.Z, T2.W, PV.Z, BS:VEC_120/SCL_212 -; EG-NEXT: AND_INT T3.W, KC0[4].X, literal.y, -; EG-NEXT: ADD_INT * T4.W, PV.Y, literal.z, +; EG-NEXT: LSHR * T5.W, PV.Z, 1, +; EG-NEXT: -127(nan), 31(4.344025e-44) +; EG-NEXT: ADD_INT T0.X, T1.W, literal.x, +; EG-NEXT: BIT_ALIGN_INT T1.Y, 0.0, PS, PV.W, +; EG-NEXT: AND_INT T2.Z, T3.W, literal.y, BS:VEC_201 +; EG-NEXT: LSHL T3.W, T0.Z, PV.Z, +; EG-NEXT: SUB_INT * T1.W, literal.z, T1.W, +; EG-NEXT: -127(nan), 32(4.484155e-44) +; EG-NEXT: 150(2.101948e-43), 0(0.000000e+00) +; EG-NEXT: AND_INT T1.X, PS, literal.x, +; EG-NEXT: BIT_ALIGN_INT T2.Y, 0.0, T0.Z, PS, +; EG-NEXT: AND_INT T0.Z, KC0[3].Z, literal.y, +; EG-NEXT: CNDE_INT T1.W, PV.Z, PV.Y, PV.W, +; EG-NEXT: SETGT_INT * T4.W, PV.X, literal.z, ; EG-NEXT: 32(4.484155e-44), 8388607(1.175494e-38) -; EG-NEXT: -150(nan), 0(0.000000e+00) -; EG-NEXT: AND_INT T2.Y, PS, literal.x, -; EG-NEXT: OR_INT T1.Z, PV.W, literal.y, -; EG-NEXT: CNDE_INT T3.W, PV.Y, PV.X, PV.Z, -; EG-NEXT: SETGT_INT * T5.W, T0.X, literal.z, -; EG-NEXT: 31(4.344025e-44), 8388608(1.175494e-38) ; EG-NEXT: 23(3.222986e-44), 0(0.000000e+00) -; EG-NEXT: CNDE_INT T3.Y, PS, 0.0, PV.W, -; EG-NEXT: SUB_INT T2.Z, literal.x, T1.W, -; EG-NEXT: LSHL T1.W, PV.Z, PV.Y, -; EG-NEXT: AND_INT * T3.W, T4.W, literal.y, -; EG-NEXT: 150(2.101948e-43), 32(4.484155e-44) -; EG-NEXT: CNDE_INT T1.X, PS, PV.W, 0.0, -; EG-NEXT: AND_INT T2.Y, PV.Z, literal.x, -; EG-NEXT: SUB_INT T3.Z, literal.y, T0.Y, -; EG-NEXT: NOT_INT T4.W, T4.W, -; EG-NEXT: LSHR * T6.W, T1.Z, 1, -; EG-NEXT: 32(4.484155e-44), 150(2.101948e-43) -; EG-NEXT: BIT_ALIGN_INT T2.X, 0.0, T2.W, T2.Z, -; EG-NEXT: ADD_INT T0.Y, T0.Y, literal.x, -; EG-NEXT: BIT_ALIGN_INT T2.Z, 0.0, PS, PV.W, -; EG-NEXT: BIT_ALIGN_INT T2.W, 0.0, T1.Z, PV.Z, -; EG-NEXT: AND_INT * T4.W, PV.Z, literal.y, -; EG-NEXT: -127(nan), 32(4.484155e-44) -; EG-NEXT: CNDE_INT T3.X, PS, PV.W, 0.0, -; EG-NEXT: CNDE_INT T4.Y, T3.W, PV.Z, T1.W, -; EG-NEXT: SETGT_INT T1.Z, PV.Y, literal.x, -; EG-NEXT: CNDE_INT T1.W, T1.Y, T0.Z, 0.0, -; EG-NEXT: CNDE_INT * T2.W, T2.Y, PV.X, 0.0, +; EG-NEXT: CNDE_INT T2.X, PS, 0.0, PV.W, +; EG-NEXT: OR_INT T1.Y, PV.Z, literal.x, +; EG-NEXT: ADD_INT T0.Z, T2.W, literal.y, +; EG-NEXT: CNDE_INT T1.W, PV.X, PV.Y, 0.0, +; EG-NEXT: CNDE_INT * T3.W, T2.Z, T3.W, 0.0, +; EG-NEXT: 8388608(1.175494e-38), -150(nan) +; EG-NEXT: CNDE_INT T1.X, T4.W, PV.W, PS, +; EG-NEXT: ASHR T2.Y, KC0[4].X, literal.x, +; EG-NEXT: AND_INT T1.Z, PV.Z, literal.x, +; EG-NEXT: NOT_INT T1.W, PV.Z, +; EG-NEXT: LSHR * T3.W, PV.Y, 1, +; EG-NEXT: 31(4.344025e-44), 0(0.000000e+00) +; EG-NEXT: BIT_ALIGN_INT T3.X, 0.0, PS, PV.W, +; EG-NEXT: LSHL T3.Y, T1.Y, PV.Z, +; EG-NEXT: XOR_INT T1.Z, PV.X, PV.Y, +; EG-NEXT: XOR_INT T1.W, T2.X, PV.Y, +; EG-NEXT: SUB_INT * T2.W, literal.x, T2.W, +; EG-NEXT: 150(2.101948e-43), 0(0.000000e+00) +; EG-NEXT: AND_INT T1.X, T0.Z, literal.x, +; EG-NEXT: AND_INT T4.Y, PS, literal.x, +; EG-NEXT: BIT_ALIGN_INT T0.Z, 0.0, T1.Y, PS, BS:VEC_021/SCL_122 +; EG-NEXT: SUB_INT T1.W, PV.W, T2.Y, +; EG-NEXT: SUBB_UINT * T2.W, PV.Z, T2.Y, +; EG-NEXT: 32(4.484155e-44), 0(0.000000e+00) +; EG-NEXT: SUB_INT T2.X, PV.W, PS, +; EG-NEXT: CNDE_INT T1.Y, PV.Y, PV.Z, 0.0, +; EG-NEXT: CNDE_INT T0.Z, PV.X, T3.Y, 0.0, +; EG-NEXT: CNDE_INT T1.W, PV.X, T3.X, T3.Y, BS:VEC_021/SCL_122 +; EG-NEXT: SETGT_INT * T2.W, T0.Y, literal.x, ; EG-NEXT: 23(3.222986e-44), 0(0.000000e+00) -; EG-NEXT: CNDE_INT T2.X, T5.W, PS, PV.W, -; EG-NEXT: ASHR T1.Y, KC0[3].Z, literal.x, -; EG-NEXT: CNDE_INT T0.Z, PV.Z, 0.0, PV.Y, -; EG-NEXT: CNDE_INT T1.W, PV.Z, PV.X, T1.X, -; EG-NEXT: ASHR * T2.W, KC0[4].X, literal.x, +; EG-NEXT: BFE_UINT T1.X, KC0[3].W, literal.x, T0.W, +; EG-NEXT: AND_INT T3.Y, KC0[3].W, literal.y, +; EG-NEXT: CNDE_INT T2.Z, PS, 0.0, PV.W, +; EG-NEXT: CNDE_INT T1.W, PS, PV.Y, PV.Z, +; EG-NEXT: ASHR * T2.W, KC0[3].Z, literal.z, +; EG-NEXT: 23(3.222986e-44), 8388607(1.175494e-38) ; EG-NEXT: 31(4.344025e-44), 0(0.000000e+00) -; EG-NEXT: XOR_INT T2.Y, PV.W, PS, +; EG-NEXT: BFE_UINT T3.X, KC0[3].Y, literal.x, T0.W, +; EG-NEXT: XOR_INT T1.Y, PV.W, PS, ; EG-NEXT: XOR_INT T0.Z, PV.Z, PS, -; EG-NEXT: XOR_INT T1.W, PV.X, PV.Y, -; EG-NEXT: XOR_INT * T3.W, T3.Y, PV.Y, -; EG-NEXT: SUB_INT T3.Y, PS, T1.Y, -; EG-NEXT: SUBB_UINT T1.Z, PV.W, T1.Y, -; EG-NEXT: SUB_INT T3.W, PV.Z, T2.W, -; EG-NEXT: SUBB_UINT * T4.W, PV.Y, T2.W, -; EG-NEXT: SUB_INT T4.Y, PV.W, PS, -; EG-NEXT: SUB_INT T0.Z, PV.Y, PV.Z, -; EG-NEXT: BFE_UINT T3.W, KC0[3].Y, literal.x, T0.W, -; EG-NEXT: AND_INT * T4.W, KC0[3].Y, literal.y, -; EG-NEXT: 23(3.222986e-44), 8388607(1.175494e-38) -; EG-NEXT: SETGT_INT T0.X, 0.0, T0.X, -; EG-NEXT: ADD_INT T3.Y, PV.W, literal.x, -; EG-NEXT: OR_INT T1.Z, PS, literal.y, -; EG-NEXT: BFE_UINT T0.W, KC0[3].W, literal.z, T0.W, -; EG-NEXT: ADD_INT * T4.W, PV.W, literal.w, -; EG-NEXT: -127(nan), 8388608(1.175494e-38) -; EG-NEXT: 23(3.222986e-44), -150(nan) -; EG-NEXT: AND_INT T1.X, KC0[3].W, literal.x, -; EG-NEXT: ADD_INT T5.Y, PV.W, literal.y, -; EG-NEXT: SUB_INT T2.Z, literal.z, T3.W, -; EG-NEXT: NOT_INT T3.W, PS, -; EG-NEXT: LSHR * T5.W, PV.Z, 1, -; EG-NEXT: 8388607(1.175494e-38), -150(nan) +; EG-NEXT: OR_INT T0.W, PV.Y, literal.y, +; EG-NEXT: SUB_INT * T1.W, literal.z, PV.X, +; EG-NEXT: 23(3.222986e-44), 8388608(1.175494e-38) ; EG-NEXT: 150(2.101948e-43), 0(0.000000e+00) -; EG-NEXT: BIT_ALIGN_INT T2.X, 0.0, PS, PV.W, -; EG-NEXT: AND_INT T6.Y, PV.Z, literal.x, -; EG-NEXT: AND_INT T3.Z, PV.Y, literal.y, -; EG-NEXT: OR_INT T3.W, PV.X, literal.z, -; EG-NEXT: AND_INT * T5.W, T4.W, literal.y, -; EG-NEXT: 32(4.484155e-44), 31(4.344025e-44) -; EG-NEXT: 8388608(1.175494e-38), 0(0.000000e+00) -; EG-NEXT: BIT_ALIGN_INT T1.X, 0.0, T1.Z, T2.Z, -; EG-NEXT: LSHL T7.Y, T1.Z, PS, -; EG-NEXT: AND_INT T1.Z, T4.W, literal.x, -; EG-NEXT: LSHL T4.W, PV.W, PV.Z, -; EG-NEXT: AND_INT * T5.W, T5.Y, literal.x, +; EG-NEXT: AND_INT T4.X, KC0[3].Y, literal.x, +; EG-NEXT: AND_INT T3.Y, PS, literal.y, +; EG-NEXT: BIT_ALIGN_INT T2.Z, 0.0, PV.W, PS, +; EG-NEXT: SUB_INT T1.W, PV.Z, T2.W, +; EG-NEXT: SUBB_UINT * T3.W, PV.Y, T2.W, +; EG-NEXT: 8388607(1.175494e-38), 32(4.484155e-44) +; EG-NEXT: SUB_INT T5.X, PV.W, PS, +; EG-NEXT: SETGT_INT T0.Y, 0.0, T0.Y, +; EG-NEXT: CNDE_INT T0.Z, PV.Y, PV.Z, 0.0, +; EG-NEXT: OR_INT T1.W, PV.X, literal.x, +; EG-NEXT: ADD_INT * T3.W, T3.X, literal.y, +; EG-NEXT: 8388608(1.175494e-38), -150(nan) +; EG-NEXT: ADD_INT T4.X, T3.X, literal.x, +; EG-NEXT: SUB_INT T3.Y, literal.y, T3.X, +; EG-NEXT: AND_INT T2.Z, PS, literal.z, +; EG-NEXT: NOT_INT T4.W, PS, +; EG-NEXT: LSHR * T5.W, PV.W, 1, +; EG-NEXT: -127(nan), 150(2.101948e-43) +; EG-NEXT: 31(4.344025e-44), 0(0.000000e+00) +; EG-NEXT: BIT_ALIGN_INT T3.X, 0.0, PS, PV.W, +; EG-NEXT: LSHL T4.Y, T1.W, PV.Z, +; EG-NEXT: AND_INT T2.Z, T3.W, literal.x, BS:VEC_120/SCL_212 +; EG-NEXT: BIT_ALIGN_INT T1.W, 0.0, T1.W, PV.Y, BS:VEC_021/SCL_122 +; EG-NEXT: AND_INT * T3.W, PV.Y, literal.x, ; EG-NEXT: 32(4.484155e-44), 0(0.000000e+00) -; EG-NEXT: CNDE_INT T3.X, PS, PV.W, 0.0, -; EG-NEXT: CNDE_INT T8.Y, PV.Z, PV.Y, 0.0, -; EG-NEXT: CNDE_INT * T2.Z, T6.Y, PV.X, 0.0, -; EG-NEXT: ALU clause starting at 106: -; EG-NEXT: CNDE_INT T6.W, T1.Z, T2.X, T7.Y, BS:VEC_021/SCL_122 -; EG-NEXT: SETGT_INT * T7.W, T3.Y, literal.x, +; EG-NEXT: ADD_INT T6.X, T1.X, literal.x, +; EG-NEXT: CNDE_INT T3.Y, PS, PV.W, 0.0, +; EG-NEXT: CNDE_INT * T3.Z, PV.Z, PV.Y, 0.0, +; EG-NEXT: -150(nan), 0(0.000000e+00) +; EG-NEXT: ALU clause starting at 108: +; EG-NEXT: CNDE_INT T1.W, T2.Z, T3.X, T4.Y, +; EG-NEXT: SETGT_INT * T3.W, T4.X, literal.x, ; EG-NEXT: 23(3.222986e-44), 0(0.000000e+00) -; EG-NEXT: CNDE_INT T1.X, PS, 0.0, PV.W, -; EG-NEXT: CNDE_INT T6.Y, PS, T2.Z, T8.Y, -; EG-NEXT: SUB_INT T1.Z, literal.x, T0.W, -; EG-NEXT: NOT_INT T6.W, T5.Y, -; EG-NEXT: LSHR * T7.W, T3.W, 1, -; EG-NEXT: 150(2.101948e-43), 0(0.000000e+00) -; EG-NEXT: ASHR T2.X, KC0[3].Y, literal.x, -; EG-NEXT: ADD_INT T5.Y, T0.W, literal.y, -; EG-NEXT: BIT_ALIGN_INT T2.Z, 0.0, PS, PV.W, -; EG-NEXT: BIT_ALIGN_INT T0.W, 0.0, T3.W, PV.Z, -; EG-NEXT: AND_INT * T3.W, PV.Z, literal.z, +; EG-NEXT: CNDE_INT T3.X, PS, 0.0, PV.W, +; EG-NEXT: CNDE_INT T3.Y, PS, T3.Y, T3.Z, +; EG-NEXT: AND_INT T2.Z, T6.X, literal.x, +; EG-NEXT: NOT_INT T1.W, T6.X, +; EG-NEXT: LSHR * T3.W, T0.W, 1, +; EG-NEXT: 31(4.344025e-44), 0(0.000000e+00) +; EG-NEXT: ASHR T7.X, KC0[3].Y, literal.x, +; EG-NEXT: ADD_INT T4.Y, T1.X, literal.y, +; EG-NEXT: BIT_ALIGN_INT T3.Z, 0.0, PS, PV.W, +; EG-NEXT: LSHL T0.W, T0.W, PV.Z, +; EG-NEXT: AND_INT * T1.W, T6.X, literal.z, ; EG-NEXT: 31(4.344025e-44), -127(nan) ; EG-NEXT: 32(4.484155e-44), 0(0.000000e+00) -; EG-NEXT: CNDE_INT T4.X, PS, PV.W, 0.0, -; EG-NEXT: CNDE_INT T7.Y, T5.W, PV.Z, T4.W, -; EG-NEXT: SETGT_INT T1.Z, PV.Y, literal.x, -; EG-NEXT: XOR_INT T0.W, T6.Y, PV.X, -; EG-NEXT: XOR_INT * T3.W, T1.X, PV.X, +; EG-NEXT: CNDE_INT T1.X, PS, PV.W, 0.0, +; EG-NEXT: CNDE_INT T5.Y, PS, PV.Z, PV.W, +; EG-NEXT: SETGT_INT T2.Z, PV.Y, literal.x, +; EG-NEXT: XOR_INT T0.W, T3.Y, PV.X, +; EG-NEXT: XOR_INT * T1.W, T3.X, PV.X, ; EG-NEXT: 23(3.222986e-44), 0(0.000000e+00) -; EG-NEXT: SUB_INT T1.X, PS, T2.X, -; EG-NEXT: SUBB_UINT T6.Y, PV.W, T2.X, -; EG-NEXT: CNDE_INT T2.Z, PV.Z, 0.0, PV.Y, -; EG-NEXT: CNDE_INT T3.W, PV.Z, PV.X, T3.X, -; EG-NEXT: ASHR * T4.W, KC0[3].W, literal.x, +; EG-NEXT: SUB_INT T3.X, PS, T7.X, +; EG-NEXT: SUBB_UINT T3.Y, PV.W, T7.X, +; EG-NEXT: CNDE_INT T3.Z, PV.Z, 0.0, PV.Y, +; EG-NEXT: CNDE_INT T1.W, PV.Z, T0.Z, PV.X, +; EG-NEXT: ASHR * T3.W, KC0[3].W, literal.x, ; EG-NEXT: 31(4.344025e-44), 0(0.000000e+00) -; EG-NEXT: XOR_INT T3.X, PV.W, PS, -; EG-NEXT: XOR_INT T7.Y, PV.Z, PS, -; EG-NEXT: SUB_INT T1.Z, PV.X, PV.Y, -; EG-NEXT: SETGT_INT T3.W, 0.0, T3.Y, -; EG-NEXT: CNDE_INT * T6.W, T0.X, T0.Z, 0.0, -; EG-NEXT: SETGT_INT T1.X, 0.0, T0.Y, +; EG-NEXT: XOR_INT T1.X, PV.W, PS, +; EG-NEXT: XOR_INT T5.Y, PV.Z, PS, +; EG-NEXT: SUB_INT T0.Z, PV.X, PV.Y, +; EG-NEXT: SETGT_INT T1.W, 0.0, T4.X, BS:VEC_021/SCL_122 +; EG-NEXT: CNDE_INT * T6.W, T0.Y, T5.X, 0.0, +; EG-NEXT: SETGT_INT T0.X, 0.0, T0.X, ; EG-NEXT: CNDE_INT T6.Y, PV.W, PV.Z, 0.0, -; EG-NEXT: SUB_INT T0.Z, T1.W, T1.Y, BS:VEC_021/SCL_122 -; EG-NEXT: SUB_INT T1.W, PV.Y, T4.W, -; EG-NEXT: SUBB_UINT * T5.W, PV.X, T4.W, -; EG-NEXT: SUB_INT T4.X, PV.W, PS, -; EG-NEXT: SETGT_INT T0.Y, 0.0, T5.Y, BS:VEC_021/SCL_122 -; EG-NEXT: CNDE_INT T6.Z, T0.X, PV.Z, 0.0, -; EG-NEXT: SUB_INT T0.W, T0.W, T2.X, -; EG-NEXT: CNDE_INT * T1.W, PV.X, T4.Y, 0.0, -; EG-NEXT: CNDE_INT T6.X, T3.W, PV.W, 0.0, -; EG-NEXT: CNDE_INT T1.Y, PV.Y, PV.X, 0.0, -; EG-NEXT: SUB_INT T0.W, T2.Y, T2.W, -; EG-NEXT: LSHR * T0.X, KC0[2].Y, literal.x, +; EG-NEXT: SUB_INT T0.Z, T1.Y, T2.W, BS:VEC_021/SCL_122 +; EG-NEXT: SUB_INT T2.W, PV.Y, T3.W, +; EG-NEXT: SUBB_UINT * T4.W, PV.X, T3.W, +; EG-NEXT: SUB_INT T3.X, PV.W, PS, +; EG-NEXT: SETGT_INT T1.Y, 0.0, T4.Y, +; EG-NEXT: CNDE_INT T6.Z, T0.Y, PV.Z, 0.0, +; EG-NEXT: SUB_INT T0.W, T0.W, T7.X, BS:VEC_021/SCL_122 +; EG-NEXT: CNDE_INT * T4.W, PV.X, T2.X, 0.0, +; EG-NEXT: CNDE_INT T6.X, T1.W, PV.W, 0.0, +; EG-NEXT: CNDE_INT T4.Y, PV.Y, PV.X, 0.0, +; EG-NEXT: SUB_INT T0.W, T1.Z, T2.Y, +; EG-NEXT: LSHR * T2.X, KC0[2].Y, literal.x, ; EG-NEXT: 2(2.802597e-45), 0(0.000000e+00) -; EG-NEXT: CNDE_INT T1.Z, T1.X, PV.W, 0.0, -; EG-NEXT: SUB_INT * T0.W, T3.X, T4.W, BS:VEC_120/SCL_212 -; EG-NEXT: CNDE_INT T1.X, T0.Y, PV.W, 0.0, +; EG-NEXT: CNDE_INT T4.Z, T0.X, PV.W, 0.0, +; EG-NEXT: SUB_INT * T0.W, T1.X, T3.W, BS:VEC_120/SCL_212 +; EG-NEXT: CNDE_INT T4.X, T1.Y, PV.W, 0.0, ; EG-NEXT: ADD_INT * T0.W, KC0[2].Y, literal.x, ; EG-NEXT: 16(2.242078e-44), 0(0.000000e+00) -; EG-NEXT: LSHR * T2.X, PV.W, literal.x, +; EG-NEXT: LSHR * T0.X, PV.W, literal.x, ; EG-NEXT: 2(2.802597e-45), 0(0.000000e+00) %conv = fptoui <4 x float> %x to <4 x i64> store <4 x i64> %conv, ptr addrspace(1) %out diff --git a/llvm/test/CodeGen/AMDGPU/llvm.exp.ll b/llvm/test/CodeGen/AMDGPU/llvm.exp.ll index 3a867879bb80..7a0450761e1f 100644 --- a/llvm/test/CodeGen/AMDGPU/llvm.exp.ll +++ b/llvm/test/CodeGen/AMDGPU/llvm.exp.ll @@ -228,23 +228,23 @@ define amdgpu_kernel void @s_exp_f32(ptr addrspace(1) %out, float %in) { ; R600-NEXT: MUL_IEEE * T2.W, PS, literal.z, ; R600-NEXT: -127(nan), 254(3.559298e-43) ; R600-NEXT: 209715200(1.972152e-31), 0(0.000000e+00) -; R600-NEXT: MUL_IEEE T3.X, PS, literal.x, -; R600-NEXT: MUL_IEEE T0.Y, T1.X, literal.y, +; R600-NEXT: MUL_IEEE T3.X, T1.X, literal.x, +; R600-NEXT: MUL_IEEE T0.Y, PS, literal.y, ; R600-NEXT: CNDE_INT T1.Z, PV.W, PV.Z, T0.Z, ; R600-NEXT: CNDE_INT T3.W, PV.Y, PV.X, T0.X, ; R600-NEXT: SETGT_INT * T4.W, T0.Z, literal.z, -; R600-NEXT: 209715200(1.972152e-31), 2130706432(1.701412e+38) +; R600-NEXT: 2130706432(1.701412e+38), 209715200(1.972152e-31) ; R600-NEXT: 127(1.779649e-43), 0(0.000000e+00) ; R600-NEXT: CNDE_INT T0.Z, PS, PV.Z, PV.W, -; R600-NEXT: MUL_IEEE T3.W, PV.Y, literal.x, -; R600-NEXT: CNDE_INT * T0.W, T0.W, PV.X, T2.W, +; R600-NEXT: CNDE_INT T0.W, T0.W, PV.Y, T2.W, +; R600-NEXT: MUL_IEEE * T2.W, PV.X, literal.x, ; R600-NEXT: 2130706432(1.701412e+38), 0(0.000000e+00) -; R600-NEXT: CNDE_INT T1.Z, T1.W, PS, T1.X, -; R600-NEXT: CNDE_INT T0.W, T1.Y, T0.Y, PV.W, +; R600-NEXT: CNDE_INT T1.Z, T1.Y, T3.X, PS, +; R600-NEXT: CNDE_INT T0.W, T1.W, PV.W, T1.X, ; R600-NEXT: LSHL * T1.W, PV.Z, literal.x, ; R600-NEXT: 23(3.222986e-44), 0(0.000000e+00) ; R600-NEXT: ADD_INT T1.W, PS, literal.x, -; R600-NEXT: CNDE_INT * T0.W, T4.W, PV.Z, PV.W, +; R600-NEXT: CNDE_INT * T0.W, T4.W, PV.W, PV.Z, ; R600-NEXT: 1065353216(1.000000e+00), 0(0.000000e+00) ; R600-NEXT: MUL_IEEE T0.W, PS, PV.W, ; R600-NEXT: SETGT * T1.W, literal.x, KC0[2].Z, @@ -258,63 +258,65 @@ define amdgpu_kernel void @s_exp_f32(ptr addrspace(1) %out, float %in) { ; ; CM-LABEL: s_exp_f32: ; CM: ; %bb.0: -; CM-NEXT: ALU 62, @4, KC0[CB0:0-32], KC1[] +; CM-NEXT: ALU 64, @4, KC0[CB0:0-32], KC1[] ; CM-NEXT: MEM_RAT_CACHELESS STORE_DWORD T0.X, T1.X ; CM-NEXT: CF_END ; CM-NEXT: PAD ; CM-NEXT: ALU clause starting at 4: ; CM-NEXT: AND_INT * T0.W, KC0[2].Z, literal.x, ; CM-NEXT: -4096(nan), 0(0.000000e+00) -; CM-NEXT: ADD * T1.W, KC0[2].Z, -PV.W, ; CM-NEXT: MUL_IEEE T0.Z, PV.W, literal.x, -; CM-NEXT: MUL_IEEE * T2.W, T0.W, literal.y, -; CM-NEXT: 967029397(3.122284e-04), 1069064192(1.442383e+00) -; CM-NEXT: RNDNE T1.Z, PV.W, +; CM-NEXT: ADD * T1.W, KC0[2].Z, -PV.W, +; CM-NEXT: 1069064192(1.442383e+00), 0(0.000000e+00) +; CM-NEXT: MUL_IEEE T1.Z, PV.W, literal.x, +; CM-NEXT: RNDNE * T2.W, PV.Z, +; CM-NEXT: 967029397(3.122284e-04), 0(0.000000e+00) +; CM-NEXT: TRUNC T2.Z, PV.W, ; CM-NEXT: MULADD_IEEE * T1.W, T1.W, literal.x, PV.Z, ; CM-NEXT: 1069064192(1.442383e+00), 0(0.000000e+00) -; CM-NEXT: MULADD_IEEE T0.Z, T0.W, literal.x, PV.W, -; CM-NEXT: ADD * T0.W, T2.W, -PV.Z, BS:VEC_120/SCL_212 +; CM-NEXT: MULADD_IEEE T0.Y, T0.W, literal.x, PV.W, +; CM-NEXT: ADD T0.Z, T0.Z, -T2.W, +; CM-NEXT: FLT_TO_INT * T0.W, PV.Z, ; CM-NEXT: 967029397(3.122284e-04), 0(0.000000e+00) -; CM-NEXT: TRUNC T1.Z, T1.Z, -; CM-NEXT: ADD * T0.W, PV.W, PV.Z, -; CM-NEXT: EXP_IEEE T0.X, T0.W, -; CM-NEXT: EXP_IEEE T0.Y (MASKED), T0.W, -; CM-NEXT: EXP_IEEE T0.Z (MASKED), T0.W, -; CM-NEXT: EXP_IEEE * T0.W (MASKED), T0.W, -; CM-NEXT: FLT_TO_INT T0.Z, T1.Z, -; CM-NEXT: MUL_IEEE * T0.W, PV.X, literal.x, -; CM-NEXT: 209715200(1.972152e-31), 0(0.000000e+00) -; CM-NEXT: MUL_IEEE T0.Y, PV.W, literal.x, -; CM-NEXT: MAX_INT T1.Z, PV.Z, literal.y, -; CM-NEXT: MIN_INT * T1.W, PV.Z, literal.z, -; CM-NEXT: 209715200(1.972152e-31), -330(nan) +; CM-NEXT: MIN_INT T1.Z, PV.W, literal.x, +; CM-NEXT: ADD * T1.W, PV.Z, PV.Y, ; CM-NEXT: 381(5.338947e-43), 0(0.000000e+00) -; CM-NEXT: ADD_INT T1.X, PV.W, literal.x, -; CM-NEXT: ADD_INT T1.Y, PV.Z, literal.y, -; CM-NEXT: ADD_INT T1.Z, T0.Z, literal.z, -; CM-NEXT: SETGT_UINT * T1.W, T0.Z, literal.w, -; CM-NEXT: -254(nan), 204(2.858649e-43) +; CM-NEXT: EXP_IEEE T0.X, T1.W, +; CM-NEXT: EXP_IEEE T0.Y (MASKED), T1.W, +; CM-NEXT: EXP_IEEE T0.Z (MASKED), T1.W, +; CM-NEXT: EXP_IEEE * T0.W (MASKED), T1.W, +; CM-NEXT: MUL_IEEE T0.Y, PV.X, literal.x, +; CM-NEXT: ADD_INT T0.Z, T1.Z, literal.y, +; CM-NEXT: MAX_INT * T1.W, T0.W, literal.z, +; CM-NEXT: 2130706432(1.701412e+38), -254(nan) +; CM-NEXT: -330(nan), 0(0.000000e+00) +; CM-NEXT: ADD_INT T1.X, T0.W, literal.x, +; CM-NEXT: ADD_INT T1.Y, PV.W, literal.y, +; CM-NEXT: ADD_INT T1.Z, T0.W, literal.z, +; CM-NEXT: SETGT_UINT * T1.W, T0.W, literal.w, +; CM-NEXT: -127(nan), 204(2.858649e-43) ; CM-NEXT: 102(1.429324e-43), -229(nan) -; CM-NEXT: ADD_INT T2.X, T0.Z, literal.x, -; CM-NEXT: SETGT_UINT T2.Y, T0.Z, literal.y, -; CM-NEXT: CNDE_INT T1.Z, PV.W, PV.Y, PV.Z, -; CM-NEXT: SETGT_INT * T2.W, T0.Z, literal.x, -; CM-NEXT: -127(nan), 254(3.559298e-43) -; CM-NEXT: MUL_IEEE T3.X, T0.X, literal.x, -; CM-NEXT: CNDE_INT T1.Y, PV.W, PV.Z, T0.Z, -; CM-NEXT: CNDE_INT T1.Z, PV.Y, PV.X, T1.X, -; CM-NEXT: SETGT_INT * T3.W, T0.Z, literal.y, -; CM-NEXT: 2130706432(1.701412e+38), 127(1.779649e-43) +; CM-NEXT: SETGT_UINT T2.X, T0.W, literal.x, ; CM-NEXT: CNDE_INT T1.Y, PV.W, PV.Y, PV.Z, -; CM-NEXT: MUL_IEEE T0.Z, PV.X, literal.x, -; CM-NEXT: CNDE_INT * T0.W, T1.W, T0.Y, T0.W, +; CM-NEXT: SETGT_INT T1.Z, T0.W, literal.y, +; CM-NEXT: MUL_IEEE * T2.W, T0.X, literal.z, +; CM-NEXT: 254(3.559298e-43), -127(nan) +; CM-NEXT: 209715200(1.972152e-31), 0(0.000000e+00) +; CM-NEXT: MUL_IEEE T3.X, PV.W, literal.x, +; CM-NEXT: CNDE_INT T1.Y, PV.Z, PV.Y, T0.W, +; CM-NEXT: CNDE_INT T0.Z, PV.X, T1.X, T0.Z, +; CM-NEXT: SETGT_INT * T0.W, T0.W, literal.y, +; CM-NEXT: 209715200(1.972152e-31), 127(1.779649e-43) +; CM-NEXT: CNDE_INT T1.Y, PV.W, PV.Y, PV.Z, +; CM-NEXT: CNDE_INT T0.Z, T1.W, PV.X, T2.W, +; CM-NEXT: MUL_IEEE * T1.W, T0.Y, literal.x, ; CM-NEXT: 2130706432(1.701412e+38), 0(0.000000e+00) -; CM-NEXT: CNDE_INT T0.Y, T2.W, PV.W, T0.X, -; CM-NEXT: CNDE_INT T0.Z, T2.Y, T3.X, PV.Z, -; CM-NEXT: LSHL * T0.W, PV.Y, literal.x, +; CM-NEXT: CNDE_INT T0.Y, T2.X, T0.Y, PV.W, +; CM-NEXT: CNDE_INT T0.Z, T1.Z, PV.Z, T0.X, +; CM-NEXT: LSHL * T1.W, PV.Y, literal.x, ; CM-NEXT: 23(3.222986e-44), 0(0.000000e+00) ; CM-NEXT: ADD_INT T1.Z, PV.W, literal.x, -; CM-NEXT: CNDE_INT * T0.W, T3.W, PV.Y, PV.Z, +; CM-NEXT: CNDE_INT * T0.W, T0.W, PV.Z, PV.Y, ; CM-NEXT: 1065353216(1.000000e+00), 0(0.000000e+00) ; CM-NEXT: MUL_IEEE T0.Z, PV.W, PV.Z, ; CM-NEXT: SETGT * T0.W, literal.x, KC0[2].Z, @@ -608,105 +610,105 @@ define amdgpu_kernel void @s_exp_v2f32(ptr addrspace(1) %out, <2 x float> %in) { ; R600-NEXT: AND_INT * T0.W, KC0[3].X, literal.x, ; R600-NEXT: -4096(nan), 0(0.000000e+00) ; R600-NEXT: ADD * T1.W, KC0[3].X, -PV.W, -; R600-NEXT: MUL_IEEE T2.W, PV.W, literal.x, -; R600-NEXT: MUL_IEEE * T3.W, T0.W, literal.y, -; R600-NEXT: 967029397(3.122284e-04), 1069064192(1.442383e+00) -; R600-NEXT: RNDNE T0.Z, PS, +; R600-NEXT: AND_INT T0.Z, KC0[2].W, literal.x, +; R600-NEXT: MUL_IEEE T2.W, PV.W, literal.y, +; R600-NEXT: MUL_IEEE * T3.W, T0.W, literal.z, +; R600-NEXT: -4096(nan), 967029397(3.122284e-04) +; R600-NEXT: 1069064192(1.442383e+00), 0(0.000000e+00) +; R600-NEXT: RNDNE T1.Z, PS, ; R600-NEXT: MULADD_IEEE T1.W, T1.W, literal.x, PV.W, -; R600-NEXT: AND_INT * T2.W, KC0[2].W, literal.y, -; R600-NEXT: 1069064192(1.442383e+00), -4096(nan) -; R600-NEXT: ADD T1.Z, KC0[2].W, -PS, +; R600-NEXT: ADD * T2.W, KC0[2].W, -PV.Z, +; R600-NEXT: 1069064192(1.442383e+00), 0(0.000000e+00) +; R600-NEXT: MUL_IEEE T0.Y, PS, literal.x, +; R600-NEXT: MUL_IEEE T2.Z, T0.Z, literal.y, ; R600-NEXT: MULADD_IEEE T0.W, T0.W, literal.x, PV.W, ; R600-NEXT: ADD * T1.W, T3.W, -PV.Z, -; R600-NEXT: 967029397(3.122284e-04), 0(0.000000e+00) -; R600-NEXT: ADD T2.Z, PS, PV.W, -; R600-NEXT: MUL_IEEE T0.W, PV.Z, literal.x, -; R600-NEXT: MUL_IEEE * T1.W, T2.W, literal.y, ; R600-NEXT: 967029397(3.122284e-04), 1069064192(1.442383e+00) -; R600-NEXT: RNDNE T0.Y, PS, -; R600-NEXT: MULADD_IEEE T1.Z, T1.Z, literal.x, PV.W, -; R600-NEXT: TRUNC T0.W, T0.Z, BS:VEC_120/SCL_212 -; R600-NEXT: EXP_IEEE * T0.X, PV.Z, +; R600-NEXT: ADD T3.Z, PS, PV.W, +; R600-NEXT: RNDNE T0.W, PV.Z, +; R600-NEXT: MULADD_IEEE * T1.W, T2.W, literal.x, PV.Y, BS:VEC_021/SCL_122 ; R600-NEXT: 1069064192(1.442383e+00), 0(0.000000e+00) -; R600-NEXT: FLT_TO_INT T1.Y, PV.W, -; R600-NEXT: MUL_IEEE T0.Z, PS, literal.x, -; R600-NEXT: MULADD_IEEE T0.W, T2.W, literal.y, PV.Z, -; R600-NEXT: ADD * T1.W, T1.W, -PV.Y, -; R600-NEXT: 209715200(1.972152e-31), 967029397(3.122284e-04) -; R600-NEXT: ADD T1.Z, PS, PV.W, -; R600-NEXT: MUL_IEEE T0.W, PV.Z, literal.x, -; R600-NEXT: SETGT_UINT * T1.W, PV.Y, literal.y, -; R600-NEXT: 209715200(1.972152e-31), -229(nan) -; R600-NEXT: CNDE_INT T0.Z, PS, PV.W, T0.Z, -; R600-NEXT: SETGT_INT T0.W, T1.Y, literal.x, -; R600-NEXT: EXP_IEEE * T1.X, PV.Z, -; R600-NEXT: -127(nan), 0(0.000000e+00) -; R600-NEXT: CNDE_INT T0.Z, PV.W, PV.Z, T0.X, -; R600-NEXT: MAX_INT T2.W, T1.Y, literal.x, -; R600-NEXT: MUL_IEEE * T3.W, PS, literal.y, -; R600-NEXT: -330(nan), 209715200(1.972152e-31) -; R600-NEXT: MUL_IEEE T2.X, PS, literal.x, -; R600-NEXT: ADD_INT T2.Y, PV.W, literal.y, -; R600-NEXT: ADD_INT T1.Z, T1.Y, literal.z, -; R600-NEXT: MIN_INT T2.W, T1.Y, literal.w, -; R600-NEXT: TRUNC * T4.W, T0.Y, -; R600-NEXT: 209715200(1.972152e-31), 204(2.858649e-43) -; R600-NEXT: 102(1.429324e-43), 381(5.338947e-43) -; R600-NEXT: FLT_TO_INT T3.X, PS, -; R600-NEXT: ADD_INT T0.Y, PV.W, literal.x, -; R600-NEXT: ADD_INT T2.Z, T1.Y, literal.y, -; R600-NEXT: SETGT_UINT T2.W, T1.Y, literal.z, -; R600-NEXT: CNDE_INT * T1.W, T1.W, PV.Y, PV.Z, -; R600-NEXT: -254(nan), -127(nan) -; R600-NEXT: 254(3.559298e-43), 0(0.000000e+00) -; R600-NEXT: MUL_IEEE T4.X, T1.X, literal.x, -; R600-NEXT: MUL_IEEE T2.Y, T0.X, literal.x, BS:VEC_120/SCL_212 -; R600-NEXT: CNDE_INT T1.Z, T0.W, PS, T1.Y, -; R600-NEXT: CNDE_INT T0.W, PV.W, PV.Z, PV.Y, -; R600-NEXT: MAX_INT * T1.W, PV.X, literal.y, +; R600-NEXT: TRUNC T0.Y, T1.Z, +; R600-NEXT: MULADD_IEEE T0.Z, T0.Z, literal.x, PS, BS:VEC_120/SCL_212 +; R600-NEXT: ADD T1.W, T2.Z, -PV.W, BS:VEC_201 +; R600-NEXT: EXP_IEEE * T0.X, PV.Z, +; R600-NEXT: 967029397(3.122284e-04), 0(0.000000e+00) +; R600-NEXT: ADD T0.Z, PV.W, PV.Z, +; R600-NEXT: FLT_TO_INT T1.W, PV.Y, +; R600-NEXT: MUL_IEEE * T2.W, PS, literal.x, +; R600-NEXT: 2130706432(1.701412e+38), 0(0.000000e+00) +; R600-NEXT: MUL_IEEE T1.Z, PS, literal.x, +; R600-NEXT: SETGT_UINT T3.W, PV.W, literal.y, +; R600-NEXT: EXP_IEEE * T0.Y, PV.Z, +; R600-NEXT: 2130706432(1.701412e+38), 254(3.559298e-43) +; R600-NEXT: CNDE_INT T1.X, PV.W, T2.W, PV.Z, +; R600-NEXT: MUL_IEEE T1.Y, PS, literal.x, +; R600-NEXT: MAX_INT T0.Z, T1.W, literal.y, +; R600-NEXT: MIN_INT T2.W, T1.W, literal.z, +; R600-NEXT: TRUNC * T0.W, T0.W, ; R600-NEXT: 2130706432(1.701412e+38), -330(nan) -; R600-NEXT: SETGT_INT T0.X, T1.Y, literal.x, -; R600-NEXT: ADD_INT T0.Y, PS, literal.y, -; R600-NEXT: ADD_INT T2.Z, T3.X, literal.z, -; R600-NEXT: SETGT_UINT * T1.W, T3.X, literal.w, +; R600-NEXT: 381(5.338947e-43), 0(0.000000e+00) +; R600-NEXT: FLT_TO_INT T2.X, PS, +; R600-NEXT: ADD_INT T2.Y, PV.W, literal.x, +; R600-NEXT: ADD_INT T0.Z, PV.Z, literal.y, +; R600-NEXT: ADD_INT T0.W, T1.W, literal.z, +; R600-NEXT: SETGT_UINT * T2.W, T1.W, literal.w, +; R600-NEXT: -254(nan), 204(2.858649e-43) +; R600-NEXT: 102(1.429324e-43), -229(nan) +; R600-NEXT: ADD_INT T3.X, T1.W, literal.x, +; R600-NEXT: CNDE_INT T3.Y, PS, PV.Z, PV.W, +; R600-NEXT: SETGT_INT T0.Z, T1.W, literal.x, +; R600-NEXT: MUL_IEEE T0.W, T0.X, literal.y, +; R600-NEXT: MUL_IEEE * T4.W, T0.Y, literal.y, +; R600-NEXT: -127(nan), 209715200(1.972152e-31) +; R600-NEXT: MUL_IEEE T4.X, PS, literal.x, +; R600-NEXT: MUL_IEEE T4.Y, PV.W, literal.x, +; R600-NEXT: CNDE_INT T1.Z, PV.Z, PV.Y, T1.W, +; R600-NEXT: CNDE_INT T3.W, T3.W, PV.X, T2.Y, +; R600-NEXT: MAX_INT * T5.W, T2.X, literal.y, +; R600-NEXT: 209715200(1.972152e-31), -330(nan) +; R600-NEXT: SETGT_INT T3.X, T1.W, literal.x, +; R600-NEXT: ADD_INT T2.Y, PS, literal.y, +; R600-NEXT: ADD_INT T2.Z, T2.X, literal.z, +; R600-NEXT: SETGT_UINT * T1.W, T2.X, literal.w, ; R600-NEXT: 127(1.779649e-43), 204(2.858649e-43) ; R600-NEXT: 102(1.429324e-43), -229(nan) -; R600-NEXT: MIN_INT * T4.W, T3.X, literal.x, +; R600-NEXT: MIN_INT * T5.W, T2.X, literal.x, ; R600-NEXT: 381(5.338947e-43), 0(0.000000e+00) ; R600-NEXT: ADD_INT T5.X, PV.W, literal.x, -; R600-NEXT: ADD_INT T1.Y, T3.X, literal.y, -; R600-NEXT: SETGT_UINT T3.Z, T3.X, literal.z, -; R600-NEXT: CNDE_INT T4.W, T1.W, T0.Y, T2.Z, -; R600-NEXT: SETGT_INT * T5.W, T3.X, literal.y, +; R600-NEXT: ADD_INT T3.Y, T2.X, literal.y, +; R600-NEXT: SETGT_UINT T3.Z, T2.X, literal.z, +; R600-NEXT: CNDE_INT T5.W, T1.W, T2.Y, T2.Z, +; R600-NEXT: SETGT_INT * T6.W, T2.X, literal.y, ; R600-NEXT: -254(nan), -127(nan) ; R600-NEXT: 254(3.559298e-43), 0(0.000000e+00) -; R600-NEXT: CNDE_INT T6.X, PS, PV.W, T3.X, -; R600-NEXT: CNDE_INT T0.Y, PV.Z, PV.Y, PV.X, -; R600-NEXT: SETGT_INT T2.Z, T3.X, literal.x, -; R600-NEXT: CNDE_INT T0.W, T0.X, T1.Z, T0.W, BS:VEC_120/SCL_212 -; R600-NEXT: MUL_IEEE * T4.W, T2.Y, literal.y, -; R600-NEXT: 127(1.779649e-43), 2130706432(1.701412e+38) -; R600-NEXT: CNDE_INT T3.X, T2.W, T2.Y, PS, BS:VEC_120/SCL_212 -; R600-NEXT: LSHL T1.Y, PV.W, literal.x, -; R600-NEXT: CNDE_INT T1.Z, PV.Z, PV.X, PV.Y, -; R600-NEXT: MUL_IEEE T0.W, T4.X, literal.y, -; R600-NEXT: CNDE_INT * T1.W, T1.W, T2.X, T3.W, +; R600-NEXT: CNDE_INT T6.X, PS, PV.W, T2.X, +; R600-NEXT: CNDE_INT T2.Y, PV.Z, PV.Y, PV.X, +; R600-NEXT: SETGT_INT T2.Z, T2.X, literal.x, BS:VEC_120/SCL_212 +; R600-NEXT: CNDE_INT T3.W, T3.X, T1.Z, T3.W, BS:VEC_021/SCL_122 +; R600-NEXT: CNDE_INT * T0.W, T2.W, T4.Y, T0.W, +; R600-NEXT: 127(1.779649e-43), 0(0.000000e+00) +; R600-NEXT: CNDE_INT T0.X, T0.Z, PS, T0.X, +; R600-NEXT: LSHL T3.Y, PV.W, literal.x, +; R600-NEXT: CNDE_INT T0.Z, PV.Z, PV.X, PV.Y, +; R600-NEXT: CNDE_INT T0.W, T1.W, T4.X, T4.W, +; R600-NEXT: MUL_IEEE * T1.W, T1.Y, literal.y, ; R600-NEXT: 23(3.222986e-44), 2130706432(1.701412e+38) -; R600-NEXT: CNDE_INT T1.X, T5.W, PS, T1.X, BS:VEC_021/SCL_122 -; R600-NEXT: CNDE_INT T0.Y, T3.Z, T4.X, PV.W, BS:VEC_201 -; R600-NEXT: LSHL T1.Z, PV.Z, literal.x, +; R600-NEXT: CNDE_INT T2.X, T3.Z, T1.Y, PS, +; R600-NEXT: CNDE_INT T0.Y, T6.W, PV.W, T0.Y, +; R600-NEXT: LSHL T0.Z, PV.Z, literal.x, ; R600-NEXT: ADD_INT T0.W, PV.Y, literal.y, -; R600-NEXT: CNDE_INT * T1.W, T0.X, T0.Z, PV.X, +; R600-NEXT: CNDE_INT * T1.W, T3.X, PV.X, T1.X, ; R600-NEXT: 23(3.222986e-44), 1065353216(1.000000e+00) ; R600-NEXT: MUL_IEEE T1.Y, PS, PV.W, -; R600-NEXT: SETGT T0.Z, literal.x, KC0[3].X, +; R600-NEXT: SETGT T1.Z, literal.x, KC0[3].X, ; R600-NEXT: ADD_INT * T0.W, PV.Z, literal.y, ; R600-NEXT: -1026650416(-1.032789e+02), 1065353216(1.000000e+00) ; R600-NEXT: ALU clause starting at 101: -; R600-NEXT: CNDE_INT * T1.W, T2.Z, T1.X, T0.Y, +; R600-NEXT: CNDE_INT * T1.W, T2.Z, T0.Y, T2.X, ; R600-NEXT: MUL_IEEE T0.Y, PV.W, T0.W, -; R600-NEXT: SETGT T1.Z, literal.x, KC0[2].W, -; R600-NEXT: CNDE T0.W, T0.Z, T1.Y, 0.0, +; R600-NEXT: SETGT T0.Z, literal.x, KC0[2].W, +; R600-NEXT: CNDE T0.W, T1.Z, T1.Y, 0.0, ; R600-NEXT: SETGT * T1.W, KC0[3].X, literal.y, ; R600-NEXT: -1026650416(-1.032789e+02), 1118925336(8.872284e+01) ; R600-NEXT: CNDE T1.Y, PS, PV.W, literal.x, @@ -719,116 +721,118 @@ define amdgpu_kernel void @s_exp_v2f32(ptr addrspace(1) %out, <2 x float> %in) { ; ; CM-LABEL: s_exp_v2f32: ; CM: ; %bb.0: -; CM-NEXT: ALU 98, @4, KC0[CB0:0-32], KC1[] -; CM-NEXT: ALU 18, @103, KC0[CB0:0-32], KC1[] +; CM-NEXT: ALU 100, @4, KC0[CB0:0-32], KC1[] +; CM-NEXT: ALU 18, @105, KC0[CB0:0-32], KC1[] ; CM-NEXT: MEM_RAT_CACHELESS STORE_DWORD T0, T1.X ; CM-NEXT: CF_END ; CM-NEXT: ALU clause starting at 4: ; CM-NEXT: AND_INT * T0.W, KC0[2].W, literal.x, ; CM-NEXT: -4096(nan), 0(0.000000e+00) +; CM-NEXT: MUL_IEEE T0.Z, PV.W, literal.x, ; CM-NEXT: ADD * T1.W, KC0[2].W, -PV.W, -; CM-NEXT: MUL_IEEE T0.Y, PV.W, literal.x, -; CM-NEXT: MUL_IEEE T0.Z, T0.W, literal.y, -; CM-NEXT: AND_INT * T2.W, KC0[3].X, literal.z, -; CM-NEXT: 967029397(3.122284e-04), 1069064192(1.442383e+00) -; CM-NEXT: -4096(nan), 0(0.000000e+00) -; CM-NEXT: ADD T1.Y, KC0[3].X, -PV.W, -; CM-NEXT: RNDNE T1.Z, PV.Z, -; CM-NEXT: MULADD_IEEE * T1.W, T1.W, literal.x, PV.Y, ; CM-NEXT: 1069064192(1.442383e+00), 0(0.000000e+00) +; CM-NEXT: MUL_IEEE T1.Z, PV.W, literal.x, +; CM-NEXT: RNDNE * T2.W, PV.Z, +; CM-NEXT: 967029397(3.122284e-04), 0(0.000000e+00) +; CM-NEXT: TRUNC T0.Y, PV.W, +; CM-NEXT: AND_INT T2.Z, KC0[3].X, literal.x, +; CM-NEXT: MULADD_IEEE * T1.W, T1.W, literal.y, PV.Z, +; CM-NEXT: -4096(nan), 1069064192(1.442383e+00) ; CM-NEXT: MULADD_IEEE T0.X, T0.W, literal.x, PV.W, -; CM-NEXT: ADD T0.Y, T0.Z, -PV.Z, -; CM-NEXT: MUL_IEEE T0.Z, PV.Y, literal.x, -; CM-NEXT: MUL_IEEE * T0.W, T2.W, literal.y, BS:VEC_120/SCL_212 +; CM-NEXT: MUL_IEEE T1.Y, PV.Z, literal.y, +; CM-NEXT: FLT_TO_INT T1.Z, PV.Y, +; CM-NEXT: ADD * T0.W, KC0[3].X, -PV.Z, ; CM-NEXT: 967029397(3.122284e-04), 1069064192(1.442383e+00) -; CM-NEXT: TRUNC T1.X, T1.Z, -; CM-NEXT: RNDNE T2.Y, PV.W, -; CM-NEXT: MULADD_IEEE T0.Z, T1.Y, literal.x, PV.Z, -; CM-NEXT: ADD * T1.W, PV.Y, PV.X, -; CM-NEXT: 1069064192(1.442383e+00), 0(0.000000e+00) -; CM-NEXT: EXP_IEEE T0.X, T1.W, -; CM-NEXT: EXP_IEEE T0.Y (MASKED), T1.W, -; CM-NEXT: EXP_IEEE T0.Z (MASKED), T1.W, -; CM-NEXT: EXP_IEEE * T0.W (MASKED), T1.W, -; CM-NEXT: MULADD_IEEE T2.X, T2.W, literal.x, T0.Z, -; CM-NEXT: ADD T0.Y, T0.W, -T2.Y, BS:VEC_120/SCL_212 -; CM-NEXT: FLT_TO_INT T0.Z, T1.X, -; CM-NEXT: MUL_IEEE * T0.W, PV.X, literal.y, -; CM-NEXT: 967029397(3.122284e-04), 209715200(1.972152e-31) -; CM-NEXT: MUL_IEEE T1.X, PV.W, literal.x, -; CM-NEXT: SETGT_UINT T1.Y, PV.Z, literal.y, -; CM-NEXT: TRUNC T1.Z, T2.Y, -; CM-NEXT: ADD * T1.W, PV.Y, PV.X, -; CM-NEXT: 209715200(1.972152e-31), -229(nan) +; CM-NEXT: ADD T1.X, T0.Z, -T2.W, +; CM-NEXT: MUL_IEEE T0.Y, PV.W, literal.x, +; CM-NEXT: MAX_INT T0.Z, PV.Z, literal.y, +; CM-NEXT: RNDNE * T1.W, PV.Y, +; CM-NEXT: 967029397(3.122284e-04), -330(nan) +; CM-NEXT: TRUNC T2.X, PV.W, +; CM-NEXT: ADD_INT T2.Y, PV.Z, literal.x, +; CM-NEXT: MULADD_IEEE T0.Z, T0.W, literal.y, PV.Y, +; CM-NEXT: ADD * T0.W, PV.X, T0.X, +; CM-NEXT: 204(2.858649e-43), 1069064192(1.442383e+00) +; CM-NEXT: EXP_IEEE T0.X, T0.W, +; CM-NEXT: EXP_IEEE T0.Y (MASKED), T0.W, +; CM-NEXT: EXP_IEEE T0.Z (MASKED), T0.W, +; CM-NEXT: EXP_IEEE * T0.W (MASKED), T0.W, +; CM-NEXT: ADD_INT T1.X, T1.Z, literal.x, +; CM-NEXT: MULADD_IEEE T0.Y, T2.Z, literal.y, T0.Z, BS:VEC_102/SCL_221 +; CM-NEXT: ADD T0.Z, T1.Y, -T1.W, +; CM-NEXT: MUL_IEEE * T0.W, PV.X, literal.z, +; CM-NEXT: 102(1.429324e-43), 967029397(3.122284e-04) +; CM-NEXT: 2130706432(1.701412e+38), 0(0.000000e+00) +; CM-NEXT: SETGT_UINT T3.X, T1.Z, literal.x, +; CM-NEXT: MUL_IEEE T1.Y, PV.W, literal.y, +; CM-NEXT: SETGT_UINT T2.Z, T1.Z, literal.z, +; CM-NEXT: ADD * T1.W, PV.Z, PV.Y, +; CM-NEXT: -229(nan), 2130706432(1.701412e+38) +; CM-NEXT: 254(3.559298e-43), 0(0.000000e+00) ; CM-NEXT: EXP_IEEE T0.X (MASKED), T1.W, ; CM-NEXT: EXP_IEEE T0.Y, T1.W, ; CM-NEXT: EXP_IEEE T0.Z (MASKED), T1.W, ; CM-NEXT: EXP_IEEE * T0.W (MASKED), T1.W, -; CM-NEXT: FLT_TO_INT T2.X, T1.Z, -; CM-NEXT: MUL_IEEE T2.Y, PV.Y, literal.x, -; CM-NEXT: CNDE_INT T1.Z, T1.Y, T1.X, T0.W, -; CM-NEXT: SETGT_INT * T0.W, T0.Z, literal.y, BS:VEC_120/SCL_212 -; CM-NEXT: 209715200(1.972152e-31), -127(nan) -; CM-NEXT: CNDE_INT T1.X, PV.W, PV.Z, T0.X, +; CM-NEXT: CNDE_INT T4.X, T2.Z, T0.W, T1.Y, +; CM-NEXT: CNDE_INT T1.Y, T3.X, T2.Y, T1.X, +; CM-NEXT: FLT_TO_INT T0.Z, T2.X, BS:VEC_120/SCL_212 +; CM-NEXT: MUL_IEEE * T0.W, PV.Y, literal.x, +; CM-NEXT: 2130706432(1.701412e+38), 0(0.000000e+00) +; CM-NEXT: SETGT_INT T1.X, T1.Z, literal.x, +; CM-NEXT: MUL_IEEE T2.Y, T0.X, literal.y, +; CM-NEXT: MUL_IEEE T3.Z, PV.W, literal.z, +; CM-NEXT: SETGT_UINT * T1.W, PV.Z, literal.w, +; CM-NEXT: -127(nan), 209715200(1.972152e-31) +; CM-NEXT: 2130706432(1.701412e+38), 254(3.559298e-43) +; CM-NEXT: CNDE_INT T2.X, PV.W, T0.W, PV.Z, ; CM-NEXT: MUL_IEEE T3.Y, PV.Y, literal.x, -; CM-NEXT: SETGT_UINT T1.Z, PV.X, literal.y, -; CM-NEXT: MAX_INT * T1.W, T0.Z, literal.z, -; CM-NEXT: 209715200(1.972152e-31), -229(nan) -; CM-NEXT: -330(nan), 0(0.000000e+00) -; CM-NEXT: ADD_INT T3.X, PV.W, literal.x, -; CM-NEXT: ADD_INT T4.Y, T0.Z, literal.y, -; CM-NEXT: CNDE_INT T2.Z, PV.Z, PV.Y, T2.Y, -; CM-NEXT: SETGT_INT * T1.W, T2.X, literal.z, +; CM-NEXT: CNDE_INT T3.Z, PV.X, T1.Y, T1.Z, +; CM-NEXT: MAX_INT * T0.W, T0.Z, literal.y, +; CM-NEXT: 209715200(1.972152e-31), -330(nan) +; CM-NEXT: ADD_INT T5.X, PV.W, literal.x, +; CM-NEXT: ADD_INT T1.Y, T0.Z, literal.y, +; CM-NEXT: SETGT_UINT T4.Z, T0.Z, literal.z, +; CM-NEXT: MUL_IEEE * T0.W, T0.Y, literal.w, ; CM-NEXT: 204(2.858649e-43), 102(1.429324e-43) +; CM-NEXT: -229(nan), 209715200(1.972152e-31) +; CM-NEXT: MUL_IEEE T6.X, PV.W, literal.x, +; CM-NEXT: MIN_INT T4.Y, T0.Z, literal.y, +; CM-NEXT: CNDE_INT T5.Z, PV.Z, PV.X, PV.Y, +; CM-NEXT: SETGT_INT * T2.W, T0.Z, literal.z, +; CM-NEXT: 209715200(1.972152e-31), 381(5.338947e-43) ; CM-NEXT: -127(nan), 0(0.000000e+00) -; CM-NEXT: CNDE_INT T4.X, PV.W, PV.Z, T0.Y, -; CM-NEXT: MUL_IEEE T2.Y, T0.X, literal.x, -; CM-NEXT: MAX_INT T2.Z, T2.X, literal.y, BS:VEC_120/SCL_212 -; CM-NEXT: CNDE_INT * T2.W, T1.Y, PV.X, PV.Y, -; CM-NEXT: 2130706432(1.701412e+38), -330(nan) -; CM-NEXT: CNDE_INT T0.X, T0.W, PV.W, T0.Z, -; CM-NEXT: ADD_INT T1.Y, PV.Z, literal.x, -; CM-NEXT: ADD_INT T2.Z, T2.X, literal.y, -; CM-NEXT: MIN_INT * T0.W, T2.X, literal.z, -; CM-NEXT: 204(2.858649e-43), 102(1.429324e-43) -; CM-NEXT: 381(5.338947e-43), 0(0.000000e+00) -; CM-NEXT: ADD_INT T3.X, PV.W, literal.x, -; CM-NEXT: ADD_INT T3.Y, T2.X, literal.y, -; CM-NEXT: SETGT_UINT T3.Z, T2.X, literal.z, -; CM-NEXT: CNDE_INT * T0.W, T1.Z, PV.Y, PV.Z, -; CM-NEXT: -254(nan), -127(nan) -; CM-NEXT: 254(3.559298e-43), 0(0.000000e+00) -; CM-NEXT: MUL_IEEE T5.X, T0.Y, literal.x, -; CM-NEXT: CNDE_INT T0.Y, T1.W, PV.W, T2.X, -; CM-NEXT: CNDE_INT T1.Z, PV.Z, PV.Y, PV.X, -; CM-NEXT: MIN_INT * T0.W, T0.Z, literal.y, -; CM-NEXT: 2130706432(1.701412e+38), 381(5.338947e-43) -; CM-NEXT: SETGT_INT T2.X, T2.X, literal.x, -; CM-NEXT: ADD_INT T1.Y, PV.W, literal.y, -; CM-NEXT: ADD_INT T2.Z, T0.Z, literal.z, -; CM-NEXT: SETGT_UINT * T0.W, T0.Z, literal.w, +; CM-NEXT: CNDE_INT T5.X, PV.W, PV.Z, T0.Z, +; CM-NEXT: MIN_INT T1.Y, T1.Z, literal.x, +; CM-NEXT: ADD_INT T5.Z, PV.Y, literal.y, +; CM-NEXT: ADD_INT * T3.W, T0.Z, literal.z, BS:VEC_120/SCL_212 +; CM-NEXT: 381(5.338947e-43), -254(nan) +; CM-NEXT: -127(nan), 0(0.000000e+00) +; CM-NEXT: CNDE_INT T7.X, T1.W, PV.W, PV.Z, +; CM-NEXT: SETGT_INT T4.Y, T0.Z, literal.x, +; CM-NEXT: ADD_INT T0.Z, PV.Y, literal.y, +; CM-NEXT: ADD_INT * T1.W, T1.Z, literal.z, BS:VEC_120/SCL_212 ; CM-NEXT: 127(1.779649e-43), -254(nan) -; CM-NEXT: -127(nan), 254(3.559298e-43) -; CM-NEXT: CNDE_INT T3.X, PV.W, PV.Z, PV.Y, -; CM-NEXT: SETGT_INT T1.Y, T0.Z, literal.x, -; CM-NEXT: CNDE_INT T0.Z, PV.X, T0.Y, T1.Z, -; CM-NEXT: MUL_IEEE * T1.W, T5.X, literal.y, -; CM-NEXT: 127(1.779649e-43), 2130706432(1.701412e+38) -; CM-NEXT: CNDE_INT T5.X, T3.Z, T5.X, PV.W, +; CM-NEXT: -127(nan), 0(0.000000e+00) +; CM-NEXT: CNDE_INT T8.X, T2.Z, PV.W, PV.Z, +; CM-NEXT: SETGT_INT T1.Y, T1.Z, literal.x, BS:VEC_120/SCL_212 +; CM-NEXT: CNDE_INT T0.Z, PV.Y, T5.X, PV.X, +; CM-NEXT: CNDE_INT * T0.W, T4.Z, T6.X, T0.W, BS:VEC_201 +; CM-NEXT: 127(1.779649e-43), 0(0.000000e+00) +; CM-NEXT: CNDE_INT T5.X, T2.W, PV.W, T0.Y, ; CM-NEXT: LSHL T0.Y, PV.Z, literal.x, -; CM-NEXT: CNDE_INT T0.Z, PV.Y, T0.X, PV.X, BS:VEC_021/SCL_122 -; CM-NEXT: MUL_IEEE * T1.W, T2.Y, literal.y, -; CM-NEXT: 23(3.222986e-44), 2130706432(1.701412e+38) -; CM-NEXT: CNDE_INT T0.X, T0.W, T2.Y, PV.W, +; CM-NEXT: CNDE_INT T0.Z, PV.Y, T3.Z, PV.X, +; CM-NEXT: CNDE_INT * T0.W, T3.X, T3.Y, T2.Y, BS:VEC_201 +; CM-NEXT: 23(3.222986e-44), 0(0.000000e+00) +; CM-NEXT: CNDE_INT T0.X, T1.X, PV.W, T0.X, ; CM-NEXT: LSHL T2.Y, PV.Z, literal.x, ; CM-NEXT: ADD_INT * T0.Z, PV.Y, literal.y, ; CM-NEXT: 23(3.222986e-44), 1065353216(1.000000e+00) -; CM-NEXT: ALU clause starting at 103: -; CM-NEXT: CNDE_INT * T0.W, T2.X, T4.X, T5.X, -; CM-NEXT: MUL_IEEE T2.X, PV.W, T0.Z, +; CM-NEXT: ALU clause starting at 105: +; CM-NEXT: CNDE_INT * T0.W, T4.Y, T5.X, T2.X, +; CM-NEXT: MUL_IEEE T1.X, PV.W, T0.Z, ; CM-NEXT: SETGT T0.Y, literal.x, KC0[3].X, ; CM-NEXT: ADD_INT T0.Z, T2.Y, literal.y, -; CM-NEXT: CNDE_INT * T0.W, T1.Y, T1.X, T0.X, BS:VEC_120/SCL_212 +; CM-NEXT: CNDE_INT * T0.W, T1.Y, T0.X, T4.X, BS:VEC_120/SCL_212 ; CM-NEXT: -1026650416(-1.032789e+02), 1065353216(1.000000e+00) ; CM-NEXT: MUL_IEEE T0.X, PV.W, PV.Z, ; CM-NEXT: SETGT T1.Y, literal.x, KC0[2].W, @@ -1211,8 +1215,8 @@ define amdgpu_kernel void @s_exp_v3f32(ptr addrspace(1) %out, <3 x float> %in) { ; ; R600-LABEL: s_exp_v3f32: ; R600: ; %bb.0: -; R600-NEXT: ALU 99, @6, KC0[CB0:0-32], KC1[] -; R600-NEXT: ALU 69, @106, KC0[CB0:0-32], KC1[] +; R600-NEXT: ALU 100, @6, KC0[CB0:0-32], KC1[] +; R600-NEXT: ALU 69, @107, KC0[CB0:0-32], KC1[] ; R600-NEXT: MEM_RAT_CACHELESS STORE_RAW T2.X, T3.X, 0 ; R600-NEXT: MEM_RAT_CACHELESS STORE_RAW T0.XY, T1.X, 1 ; R600-NEXT: CF_END @@ -1220,68 +1224,69 @@ define amdgpu_kernel void @s_exp_v3f32(ptr addrspace(1) %out, <3 x float> %in) { ; R600-NEXT: ALU clause starting at 6: ; R600-NEXT: AND_INT * T0.W, KC0[3].Y, literal.x, ; R600-NEXT: -4096(nan), 0(0.000000e+00) -; R600-NEXT: MUL_IEEE T1.W, PV.W, literal.x, -; R600-NEXT: ADD * T2.W, KC0[3].Y, -PV.W, +; R600-NEXT: ADD T1.W, KC0[3].Y, -PV.W, +; R600-NEXT: MUL_IEEE * T2.W, PV.W, literal.x, ; R600-NEXT: 1069064192(1.442383e+00), 0(0.000000e+00) -; R600-NEXT: RNDNE * T3.W, PV.W, -; R600-NEXT: TRUNC T4.W, PV.W, -; R600-NEXT: MUL_IEEE * T5.W, T2.W, literal.x, +; R600-NEXT: RNDNE T3.W, PS, +; R600-NEXT: MUL_IEEE * T4.W, PV.W, literal.x, ; R600-NEXT: 967029397(3.122284e-04), 0(0.000000e+00) -; R600-NEXT: MULADD_IEEE T2.W, T2.W, literal.x, PS, -; R600-NEXT: FLT_TO_INT * T4.W, PV.W, +; R600-NEXT: MULADD_IEEE T1.W, T1.W, literal.x, PS, +; R600-NEXT: TRUNC * T4.W, PV.W, ; R600-NEXT: 1069064192(1.442383e+00), 0(0.000000e+00) -; R600-NEXT: MAX_INT T0.Z, PS, literal.x, -; R600-NEXT: MULADD_IEEE T0.W, T0.W, literal.y, PV.W, -; R600-NEXT: ADD * T1.W, T1.W, -T3.W, -; R600-NEXT: -330(nan), 967029397(3.122284e-04) -; R600-NEXT: ADD T0.Y, PS, PV.W, -; R600-NEXT: ADD_INT T0.Z, PV.Z, literal.x, -; R600-NEXT: ADD_INT T0.W, T4.W, literal.y, -; R600-NEXT: SETGT_UINT * T1.W, T4.W, literal.z, +; R600-NEXT: FLT_TO_INT T0.Z, PS, +; R600-NEXT: MULADD_IEEE T0.W, T0.W, literal.x, PV.W, +; R600-NEXT: ADD * T1.W, T2.W, -T3.W, +; R600-NEXT: 967029397(3.122284e-04), 0(0.000000e+00) +; R600-NEXT: ADD T0.W, PS, PV.W, +; R600-NEXT: MAX_INT * T1.W, PV.Z, literal.x, +; R600-NEXT: -330(nan), 0(0.000000e+00) +; R600-NEXT: ADD_INT T0.Y, PS, literal.x, +; R600-NEXT: ADD_INT T1.Z, T0.Z, literal.y, +; R600-NEXT: SETGT_UINT T1.W, T0.Z, literal.z, +; R600-NEXT: EXP_IEEE * T0.X, PV.W, ; R600-NEXT: 204(2.858649e-43), 102(1.429324e-43) ; R600-NEXT: -229(nan), 0(0.000000e+00) -; R600-NEXT: CNDE_INT T0.Z, PS, PV.Z, PV.W, -; R600-NEXT: SETGT_INT T0.W, T4.W, literal.x, -; R600-NEXT: EXP_IEEE * T0.X, PV.Y, -; R600-NEXT: -127(nan), 0(0.000000e+00) -; R600-NEXT: MUL_IEEE T1.X, PS, literal.x, -; R600-NEXT: CNDE_INT T0.Y, PV.W, PV.Z, T4.W, -; R600-NEXT: MIN_INT T0.Z, T4.W, literal.y, -; R600-NEXT: AND_INT T2.W, KC0[3].W, literal.z, -; R600-NEXT: MUL_IEEE * T3.W, PS, literal.w, -; R600-NEXT: 2130706432(1.701412e+38), 381(5.338947e-43) -; R600-NEXT: -4096(nan), 209715200(1.972152e-31) -; R600-NEXT: MUL_IEEE T2.X, PS, literal.x, -; R600-NEXT: ADD T1.Y, KC0[3].W, -PV.W, -; R600-NEXT: ADD_INT T0.Z, PV.Z, literal.y, -; R600-NEXT: ADD_INT T5.W, T4.W, literal.z, -; R600-NEXT: SETGT_UINT * T6.W, T4.W, literal.w, -; R600-NEXT: 209715200(1.972152e-31), -254(nan) +; R600-NEXT: CNDE_INT T1.Z, PV.W, PV.Y, PV.Z, +; R600-NEXT: SETGT_INT T0.W, T0.Z, literal.x, +; R600-NEXT: MUL_IEEE * T2.W, PS, literal.y, +; R600-NEXT: -127(nan), 209715200(1.972152e-31) +; R600-NEXT: MUL_IEEE T0.Y, PS, literal.x, +; R600-NEXT: CNDE_INT T1.Z, PV.W, PV.Z, T0.Z, +; R600-NEXT: MIN_INT T3.W, T0.Z, literal.y, +; R600-NEXT: AND_INT * T4.W, KC0[3].W, literal.z, +; R600-NEXT: 209715200(1.972152e-31), 381(5.338947e-43) +; R600-NEXT: -4096(nan), 0(0.000000e+00) +; R600-NEXT: MUL_IEEE T1.X, T0.X, literal.x, +; R600-NEXT: ADD T1.Y, KC0[3].W, -PS, +; R600-NEXT: ADD_INT T2.Z, PV.W, literal.y, +; R600-NEXT: ADD_INT T3.W, T0.Z, literal.z, +; R600-NEXT: SETGT_UINT * T5.W, T0.Z, literal.w, +; R600-NEXT: 2130706432(1.701412e+38), -254(nan) ; R600-NEXT: -127(nan), 254(3.559298e-43) -; R600-NEXT: CNDE_INT T3.X, PS, PV.W, PV.Z, -; R600-NEXT: SETGT_INT T2.Y, T4.W, literal.x, +; R600-NEXT: CNDE_INT T2.X, PS, PV.W, PV.Z, +; R600-NEXT: SETGT_INT T2.Y, T0.Z, literal.x, ; R600-NEXT: MUL_IEEE T0.Z, PV.Y, literal.y, -; R600-NEXT: MUL_IEEE * T4.W, T2.W, literal.z, BS:VEC_120/SCL_212 +; R600-NEXT: MUL_IEEE T3.W, T4.W, literal.z, +; R600-NEXT: MUL_IEEE * T6.W, PV.X, literal.w, ; R600-NEXT: 127(1.779649e-43), 967029397(3.122284e-04) -; R600-NEXT: 1069064192(1.442383e+00), 0(0.000000e+00) -; R600-NEXT: CNDE_INT * T1.W, T1.W, T2.X, T3.W, -; R600-NEXT: CNDE_INT T0.X, T0.W, PV.W, T0.X, BS:VEC_021/SCL_122 -; R600-NEXT: RNDNE T3.Y, T4.W, BS:VEC_120/SCL_212 -; R600-NEXT: MULADD_IEEE T0.Z, T1.Y, literal.x, T0.Z, -; R600-NEXT: CNDE_INT T0.W, T2.Y, T0.Y, T3.X, BS:VEC_120/SCL_212 -; R600-NEXT: MUL_IEEE * T1.W, T1.X, literal.y, ; R600-NEXT: 1069064192(1.442383e+00), 2130706432(1.701412e+38) -; R600-NEXT: CNDE_INT T1.X, T6.W, T1.X, PS, +; R600-NEXT: CNDE_INT T1.X, T5.W, T1.X, PS, BS:VEC_120/SCL_212 +; R600-NEXT: RNDNE T3.Y, PV.W, +; R600-NEXT: MULADD_IEEE T0.Z, T1.Y, literal.x, PV.Z, +; R600-NEXT: CNDE_INT T5.W, PV.Y, T1.Z, PV.X, +; R600-NEXT: CNDE_INT * T1.W, T1.W, T0.Y, T2.W, +; R600-NEXT: 1069064192(1.442383e+00), 0(0.000000e+00) +; R600-NEXT: CNDE_INT T0.X, T0.W, PS, T0.X, ; R600-NEXT: LSHL T0.Y, PV.W, literal.x, ; R600-NEXT: AND_INT T1.Z, KC0[3].Z, literal.y, -; R600-NEXT: MULADD_IEEE T0.W, T2.W, literal.z, PV.Z, BS:VEC_120/SCL_212 -; R600-NEXT: ADD * T1.W, T4.W, -PV.Y, +; R600-NEXT: MULADD_IEEE T0.W, T4.W, literal.z, PV.Z, BS:VEC_120/SCL_212 +; R600-NEXT: ADD * T1.W, T3.W, -PV.Y, ; R600-NEXT: 23(3.222986e-44), -4096(nan) ; R600-NEXT: 967029397(3.122284e-04), 0(0.000000e+00) ; R600-NEXT: ADD T1.Y, PS, PV.W, ; R600-NEXT: MUL_IEEE T0.Z, PV.Z, literal.x, ; R600-NEXT: ADD_INT T0.W, PV.Y, literal.y, -; R600-NEXT: CNDE_INT * T1.W, T2.Y, T0.X, PV.X, +; R600-NEXT: CNDE_INT * T1.W, T2.Y, PV.X, T1.X, ; R600-NEXT: 1069064192(1.442383e+00), 1065353216(1.000000e+00) ; R600-NEXT: MUL_IEEE T0.X, PS, PV.W, ; R600-NEXT: ADD T0.Y, KC0[3].Z, -T1.Z, @@ -1295,12 +1300,12 @@ define amdgpu_kernel void @s_exp_v3f32(ptr addrspace(1) %out, <3 x float> %in) { ; R600-NEXT: MUL_IEEE * T1.W, PS, literal.z, ; R600-NEXT: -1026650416(-1.032789e+02), 967029397(3.122284e-04) ; R600-NEXT: 209715200(1.972152e-31), 0(0.000000e+00) -; R600-NEXT: MUL_IEEE T3.X, PS, literal.x, -; R600-NEXT: MUL_IEEE T2.Y, T1.X, literal.y, +; R600-NEXT: MUL_IEEE T3.X, T1.X, literal.x, +; R600-NEXT: MUL_IEEE T2.Y, PS, literal.y, ; R600-NEXT: MULADD_IEEE T4.Z, T0.Y, literal.z, PV.W, ; R600-NEXT: FLT_TO_INT T0.W, PV.Z, ; R600-NEXT: MIN_INT * T2.W, PV.Y, literal.w, -; R600-NEXT: 209715200(1.972152e-31), 2130706432(1.701412e+38) +; R600-NEXT: 2130706432(1.701412e+38), 209715200(1.972152e-31) ; R600-NEXT: 1069064192(1.442383e+00), 381(5.338947e-43) ; R600-NEXT: ADD_INT T4.X, PS, literal.x, ; R600-NEXT: MAX_INT T0.Y, PV.W, literal.y, @@ -1318,7 +1323,7 @@ define amdgpu_kernel void @s_exp_v3f32(ptr addrspace(1) %out, <3 x float> %in) { ; R600-NEXT: 102(1.429324e-43), -229(nan) ; R600-NEXT: ADD_INT * T6.X, T0.W, literal.x, ; R600-NEXT: -127(nan), 0(0.000000e+00) -; R600-NEXT: ALU clause starting at 106: +; R600-NEXT: ALU clause starting at 107: ; R600-NEXT: SETGT_UINT T0.Y, T0.W, literal.x, ; R600-NEXT: CNDE_INT T0.Z, T3.W, T0.Z, T2.W, BS:VEC_102/SCL_221 ; R600-NEXT: SETGT_INT T2.W, T0.W, literal.y, @@ -1334,25 +1339,25 @@ define amdgpu_kernel void @s_exp_v3f32(ptr addrspace(1) %out, <3 x float> %in) { ; R600-NEXT: SETGT_UINT T5.X, T1.Y, literal.x, ; R600-NEXT: CNDE_INT T4.Y, PS, PV.Z, PV.W, ; R600-NEXT: MAX_INT T0.Z, T1.Y, literal.y, -; R600-NEXT: MUL_IEEE T4.W, PV.Y, literal.z, -; R600-NEXT: MUL_IEEE * T5.W, T1.Z, literal.w, +; R600-NEXT: MUL_IEEE T4.W, T1.Z, literal.z, +; R600-NEXT: MUL_IEEE * T5.W, PV.Y, literal.w, ; R600-NEXT: 254(3.559298e-43), -330(nan) -; R600-NEXT: 209715200(1.972152e-31), 2130706432(1.701412e+38) -; R600-NEXT: MUL_IEEE T6.X, PS, literal.x, -; R600-NEXT: CNDE_INT T3.Y, T3.W, PV.W, T3.Y, BS:VEC_021/SCL_122 +; R600-NEXT: 2130706432(1.701412e+38), 209715200(1.972152e-31) +; R600-NEXT: CNDE_INT T6.X, T3.W, PS, T3.Y, BS:VEC_021/SCL_122 +; R600-NEXT: MUL_IEEE T3.Y, PV.W, literal.x, ; R600-NEXT: ADD_INT T0.Z, PV.Z, literal.y, ; R600-NEXT: ADD_INT T3.W, T1.Y, literal.z, -; R600-NEXT: SETGT_UINT * T4.W, T1.Y, literal.w, +; R600-NEXT: SETGT_UINT * T5.W, T1.Y, literal.w, ; R600-NEXT: 2130706432(1.701412e+38), 204(2.858649e-43) ; R600-NEXT: 102(1.429324e-43), -229(nan) ; R600-NEXT: CNDE_INT T8.X, PS, PV.Z, PV.W, ; R600-NEXT: SETGT_INT T5.Y, T1.Y, literal.x, -; R600-NEXT: CNDE_INT T0.Z, T2.W, PV.Y, T1.Z, -; R600-NEXT: CNDE_INT T2.W, T0.Y, T5.W, PV.X, BS:VEC_120/SCL_212 +; R600-NEXT: CNDE_INT T0.Z, T0.Y, T4.W, PV.Y, BS:VEC_120/SCL_212 +; R600-NEXT: CNDE_INT T2.W, T2.W, PV.X, T1.Z, ; R600-NEXT: LSHL * T3.W, T4.Y, literal.y, ; R600-NEXT: -127(nan), 23(3.222986e-44) ; R600-NEXT: ADD_INT T6.X, PS, literal.x, -; R600-NEXT: CNDE_INT T0.Y, T0.W, PV.Z, PV.W, +; R600-NEXT: CNDE_INT T0.Y, T0.W, PV.W, PV.Z, ; R600-NEXT: CNDE_INT T0.Z, PV.Y, PV.X, T1.Y, ; R600-NEXT: CNDE_INT T0.W, T5.X, T7.X, T4.X, ; R600-NEXT: SETGT_INT * T2.W, T1.Y, literal.y, @@ -1360,18 +1365,18 @@ define amdgpu_kernel void @s_exp_v3f32(ptr addrspace(1) %out, <3 x float> %in) { ; R600-NEXT: CNDE_INT T4.X, PS, PV.Z, PV.W, ; R600-NEXT: MUL_IEEE T0.Y, PV.Y, PV.X, ; R600-NEXT: SETGT T0.Z, literal.x, KC0[3].Z, -; R600-NEXT: MUL_IEEE T0.W, T2.Y, literal.y, -; R600-NEXT: CNDE_INT * T1.W, T4.W, T3.X, T1.W, +; R600-NEXT: CNDE_INT T0.W, T5.W, T2.Y, T1.W, +; R600-NEXT: MUL_IEEE * T1.W, T3.X, literal.y, ; R600-NEXT: -1026650416(-1.032789e+02), 2130706432(1.701412e+38) -; R600-NEXT: CNDE_INT T1.X, T5.Y, PS, T1.X, -; R600-NEXT: CNDE_INT T1.Y, T5.X, T2.Y, PV.W, +; R600-NEXT: CNDE_INT T3.X, T5.X, T3.X, PS, +; R600-NEXT: CNDE_INT T1.Y, T5.Y, PV.W, T1.X, ; R600-NEXT: CNDE T0.Z, PV.Z, PV.Y, 0.0, ; R600-NEXT: SETGT T0.W, KC0[3].Z, literal.x, ; R600-NEXT: LSHL * T1.W, PV.X, literal.y, ; R600-NEXT: 1118925336(8.872284e+01), 23(3.222986e-44) -; R600-NEXT: ADD_INT T3.X, PS, literal.x, +; R600-NEXT: ADD_INT T1.X, PS, literal.x, ; R600-NEXT: CNDE T0.Y, PV.W, PV.Z, literal.y, -; R600-NEXT: CNDE_INT T0.Z, T2.W, PV.X, PV.Y, +; R600-NEXT: CNDE_INT T0.Z, T2.W, PV.Y, PV.X, ; R600-NEXT: CNDE T0.W, T2.X, T0.X, 0.0, ; R600-NEXT: SETGT * T1.W, KC0[3].Y, literal.z, ; R600-NEXT: 1065353216(1.000000e+00), 2139095040(INF) @@ -1392,193 +1397,197 @@ define amdgpu_kernel void @s_exp_v3f32(ptr addrspace(1) %out, <3 x float> %in) { ; ; CM-LABEL: s_exp_v3f32: ; CM: ; %bb.0: -; CM-NEXT: ALU 101, @6, KC0[CB0:0-32], KC1[] -; CM-NEXT: ALU 77, @108, KC0[CB0:0-32], KC1[] -; CM-NEXT: MEM_RAT_CACHELESS STORE_DWORD T0, T1.X -; CM-NEXT: MEM_RAT_CACHELESS STORE_DWORD T2.X, T3.X +; CM-NEXT: ALU 102, @6, KC0[CB0:0-32], KC1[] +; CM-NEXT: ALU 80, @109, KC0[CB0:0-32], KC1[] +; CM-NEXT: MEM_RAT_CACHELESS STORE_DWORD T1, T3.X +; CM-NEXT: MEM_RAT_CACHELESS STORE_DWORD T2.X, T0.X ; CM-NEXT: CF_END ; CM-NEXT: PAD ; CM-NEXT: ALU clause starting at 6: ; CM-NEXT: AND_INT * T0.W, KC0[3].Y, literal.x, ; CM-NEXT: -4096(nan), 0(0.000000e+00) -; CM-NEXT: ADD * T1.W, KC0[3].Y, -PV.W, ; CM-NEXT: MUL_IEEE T0.Z, PV.W, literal.x, -; CM-NEXT: MUL_IEEE * T2.W, T0.W, literal.y, -; CM-NEXT: 967029397(3.122284e-04), 1069064192(1.442383e+00) -; CM-NEXT: RNDNE T1.Z, PV.W, +; CM-NEXT: ADD * T1.W, KC0[3].Y, -PV.W, +; CM-NEXT: 1069064192(1.442383e+00), 0(0.000000e+00) +; CM-NEXT: MUL_IEEE T1.Z, PV.W, literal.x, +; CM-NEXT: RNDNE * T2.W, PV.Z, +; CM-NEXT: 967029397(3.122284e-04), 0(0.000000e+00) +; CM-NEXT: TRUNC T2.Z, PV.W, ; CM-NEXT: MULADD_IEEE * T1.W, T1.W, literal.x, PV.Z, ; CM-NEXT: 1069064192(1.442383e+00), 0(0.000000e+00) -; CM-NEXT: MULADD_IEEE T0.Z, T0.W, literal.x, PV.W, -; CM-NEXT: ADD * T0.W, T2.W, -PV.Z, BS:VEC_120/SCL_212 +; CM-NEXT: MULADD_IEEE T0.Y, T0.W, literal.x, PV.W, +; CM-NEXT: ADD T0.Z, T0.Z, -T2.W, +; CM-NEXT: FLT_TO_INT * T0.W, PV.Z, ; CM-NEXT: 967029397(3.122284e-04), 0(0.000000e+00) -; CM-NEXT: TRUNC T1.Z, T1.Z, -; CM-NEXT: ADD * T0.W, PV.W, PV.Z, -; CM-NEXT: EXP_IEEE T0.X, T0.W, -; CM-NEXT: EXP_IEEE T0.Y (MASKED), T0.W, -; CM-NEXT: EXP_IEEE T0.Z (MASKED), T0.W, -; CM-NEXT: EXP_IEEE * T0.W (MASKED), T0.W, -; CM-NEXT: FLT_TO_INT T0.Z, T1.Z, -; CM-NEXT: MUL_IEEE * T0.W, PV.X, literal.x, -; CM-NEXT: 209715200(1.972152e-31), 0(0.000000e+00) -; CM-NEXT: MUL_IEEE T0.Y, PV.W, literal.x, -; CM-NEXT: MAX_INT T1.Z, PV.Z, literal.y, -; CM-NEXT: MIN_INT * T1.W, PV.Z, literal.z, -; CM-NEXT: 209715200(1.972152e-31), -330(nan) +; CM-NEXT: MIN_INT T1.Z, PV.W, literal.x, +; CM-NEXT: ADD * T1.W, PV.Z, PV.Y, ; CM-NEXT: 381(5.338947e-43), 0(0.000000e+00) -; CM-NEXT: ADD_INT T1.X, PV.W, literal.x, -; CM-NEXT: ADD_INT T1.Y, PV.Z, literal.y, -; CM-NEXT: ADD_INT T1.Z, T0.Z, literal.z, -; CM-NEXT: SETGT_UINT * T1.W, T0.Z, literal.w, -; CM-NEXT: -254(nan), 204(2.858649e-43) +; CM-NEXT: EXP_IEEE T0.X, T1.W, +; CM-NEXT: EXP_IEEE T0.Y (MASKED), T1.W, +; CM-NEXT: EXP_IEEE T0.Z (MASKED), T1.W, +; CM-NEXT: EXP_IEEE * T0.W (MASKED), T1.W, +; CM-NEXT: MUL_IEEE T0.Y, PV.X, literal.x, +; CM-NEXT: ADD_INT T0.Z, T1.Z, literal.y, +; CM-NEXT: MAX_INT * T1.W, T0.W, literal.z, +; CM-NEXT: 2130706432(1.701412e+38), -254(nan) +; CM-NEXT: -330(nan), 0(0.000000e+00) +; CM-NEXT: ADD_INT T1.X, T0.W, literal.x, +; CM-NEXT: ADD_INT T1.Y, PV.W, literal.y, +; CM-NEXT: ADD_INT T1.Z, T0.W, literal.z, +; CM-NEXT: SETGT_UINT * T1.W, T0.W, literal.w, +; CM-NEXT: -127(nan), 204(2.858649e-43) ; CM-NEXT: 102(1.429324e-43), -229(nan) -; CM-NEXT: ADD_INT T2.X, T0.Z, literal.x, -; CM-NEXT: SETGT_UINT T2.Y, T0.Z, literal.y, -; CM-NEXT: CNDE_INT T1.Z, PV.W, PV.Y, PV.Z, -; CM-NEXT: SETGT_INT * T2.W, T0.Z, literal.x, -; CM-NEXT: -127(nan), 254(3.559298e-43) -; CM-NEXT: MUL_IEEE T3.X, T0.X, literal.x, -; CM-NEXT: CNDE_INT T1.Y, PV.W, PV.Z, T0.Z, -; CM-NEXT: CNDE_INT T1.Z, PV.Y, PV.X, T1.X, -; CM-NEXT: SETGT_INT * T3.W, T0.Z, literal.y, -; CM-NEXT: 2130706432(1.701412e+38), 127(1.779649e-43) +; CM-NEXT: SETGT_UINT T2.X, T0.W, literal.x, +; CM-NEXT: CNDE_INT T1.Y, PV.W, PV.Y, PV.Z, +; CM-NEXT: SETGT_INT T1.Z, T0.W, literal.y, +; CM-NEXT: MUL_IEEE * T2.W, T0.X, literal.z, +; CM-NEXT: 254(3.559298e-43), -127(nan) +; CM-NEXT: 209715200(1.972152e-31), 0(0.000000e+00) +; CM-NEXT: MUL_IEEE T3.X, PV.W, literal.x, +; CM-NEXT: CNDE_INT T1.Y, PV.Z, PV.Y, T0.W, +; CM-NEXT: CNDE_INT T0.Z, PV.X, T1.X, T0.Z, +; CM-NEXT: SETGT_INT * T0.W, T0.W, literal.y, +; CM-NEXT: 209715200(1.972152e-31), 127(1.779649e-43) ; CM-NEXT: CNDE_INT T1.Y, PV.W, PV.Y, PV.Z, -; CM-NEXT: MUL_IEEE T0.Z, PV.X, literal.x, -; CM-NEXT: CNDE_INT * T0.W, T1.W, T0.Y, T0.W, +; CM-NEXT: CNDE_INT T0.Z, T1.W, PV.X, T2.W, +; CM-NEXT: MUL_IEEE * T1.W, T0.Y, literal.x, ; CM-NEXT: 2130706432(1.701412e+38), 0(0.000000e+00) -; CM-NEXT: CNDE_INT T0.X, T2.W, PV.W, T0.X, -; CM-NEXT: CNDE_INT T0.Y, T2.Y, T3.X, PV.Z, +; CM-NEXT: CNDE_INT T1.X, T2.X, T0.Y, PV.W, +; CM-NEXT: CNDE_INT T0.Y, T1.Z, PV.Z, T0.X, ; CM-NEXT: LSHL T0.Z, PV.Y, literal.x, -; CM-NEXT: AND_INT * T0.W, KC0[3].Z, literal.y, +; CM-NEXT: AND_INT * T1.W, KC0[3].Z, literal.y, ; CM-NEXT: 23(3.222986e-44), -4096(nan) +; CM-NEXT: MUL_IEEE T0.X, PV.W, literal.x, ; CM-NEXT: ADD T1.Y, KC0[3].Z, -PV.W, -; CM-NEXT: ADD_INT T0.Z, PV.Z, literal.x, -; CM-NEXT: CNDE_INT * T1.W, T3.W, PV.X, PV.Y, -; CM-NEXT: 1065353216(1.000000e+00), 0(0.000000e+00) -; CM-NEXT: MUL_IEEE T0.X, PV.W, PV.Z, -; CM-NEXT: MUL_IEEE T0.Y, PV.Y, literal.x, -; CM-NEXT: MUL_IEEE T0.Z, T0.W, literal.y, -; CM-NEXT: AND_INT * T1.W, KC0[3].W, literal.z, -; CM-NEXT: 967029397(3.122284e-04), 1069064192(1.442383e+00) -; CM-NEXT: -4096(nan), 0(0.000000e+00) -; CM-NEXT: SETGT T1.X, literal.x, KC0[3].Y, -; CM-NEXT: ADD T2.Y, KC0[3].W, -PV.W, -; CM-NEXT: RNDNE T1.Z, PV.Z, -; CM-NEXT: MULADD_IEEE * T2.W, T1.Y, literal.y, PV.Y, -; CM-NEXT: -1026650416(-1.032789e+02), 1069064192(1.442383e+00) -; CM-NEXT: MULADD_IEEE T2.X, T0.W, literal.x, PV.W, -; CM-NEXT: ADD T0.Y, T0.Z, -PV.Z, +; CM-NEXT: ADD_INT T0.Z, PV.Z, literal.y, +; CM-NEXT: CNDE_INT * T0.W, T0.W, PV.Y, PV.X, +; CM-NEXT: 1069064192(1.442383e+00), 1065353216(1.000000e+00) +; CM-NEXT: MUL_IEEE T0.Y, PV.W, PV.Z, ; CM-NEXT: MUL_IEEE T0.Z, PV.Y, literal.x, -; CM-NEXT: MUL_IEEE * T0.W, T1.W, literal.y, BS:VEC_120/SCL_212 -; CM-NEXT: 967029397(3.122284e-04), 1069064192(1.442383e+00) -; CM-NEXT: TRUNC T3.X, T1.Z, -; CM-NEXT: RNDNE T1.Y, PV.W, -; CM-NEXT: MULADD_IEEE T0.Z, T2.Y, literal.x, PV.Z, -; CM-NEXT: ADD * T2.W, PV.Y, PV.X, +; CM-NEXT: RNDNE * T0.W, PV.X, +; CM-NEXT: 967029397(3.122284e-04), 0(0.000000e+00) +; CM-NEXT: SETGT T1.X, literal.x, KC0[3].Y, +; CM-NEXT: TRUNC T2.Y, PV.W, +; CM-NEXT: AND_INT T1.Z, KC0[3].W, literal.y, +; CM-NEXT: MULADD_IEEE * T2.W, T1.Y, literal.z, PV.Z, +; CM-NEXT: -1026650416(-1.032789e+02), -4096(nan) ; CM-NEXT: 1069064192(1.442383e+00), 0(0.000000e+00) -; CM-NEXT: EXP_IEEE T0.X (MASKED), T2.W, -; CM-NEXT: EXP_IEEE T0.Y, T2.W, -; CM-NEXT: EXP_IEEE T0.Z (MASKED), T2.W, -; CM-NEXT: EXP_IEEE * T0.W (MASKED), T2.W, -; CM-NEXT: MULADD_IEEE T2.X, T1.W, literal.x, T0.Z, -; CM-NEXT: ADD T2.Y, T0.W, -T1.Y, BS:VEC_120/SCL_212 -; CM-NEXT: FLT_TO_INT T0.Z, T3.X, -; CM-NEXT: MUL_IEEE * T0.W, PV.Y, literal.y, -; CM-NEXT: 967029397(3.122284e-04), 209715200(1.972152e-31) -; CM-NEXT: MUL_IEEE T3.X, PV.W, literal.x, -; CM-NEXT: SETGT_UINT T3.Y, PV.Z, literal.y, -; CM-NEXT: TRUNC T1.Z, T1.Y, -; CM-NEXT: ADD * T1.W, PV.Y, PV.X, -; CM-NEXT: 209715200(1.972152e-31), -229(nan) +; CM-NEXT: MULADD_IEEE T2.X, T1.W, literal.x, PV.W, +; CM-NEXT: MUL_IEEE T1.Y, PV.Z, literal.y, +; CM-NEXT: FLT_TO_INT T0.Z, PV.Y, +; CM-NEXT: ADD * T1.W, KC0[3].W, -PV.Z, +; CM-NEXT: 967029397(3.122284e-04), 1069064192(1.442383e+00) +; CM-NEXT: ADD T0.X, T0.X, -T0.W, +; CM-NEXT: MUL_IEEE T2.Y, PV.W, literal.x, +; CM-NEXT: MAX_INT T2.Z, PV.Z, literal.y, +; CM-NEXT: RNDNE * T0.W, PV.Y, +; CM-NEXT: 967029397(3.122284e-04), -330(nan) +; CM-NEXT: TRUNC T3.X, PV.W, +; CM-NEXT: ADD_INT T3.Y, PV.Z, literal.x, +; CM-NEXT: MULADD_IEEE T2.Z, T1.W, literal.y, PV.Y, +; CM-NEXT: ADD * T1.W, PV.X, T2.X, +; CM-NEXT: 204(2.858649e-43), 1069064192(1.442383e+00) +; CM-NEXT: EXP_IEEE T0.X, T1.W, +; CM-NEXT: EXP_IEEE T0.Y (MASKED), T1.W, +; CM-NEXT: EXP_IEEE T0.Z (MASKED), T1.W, +; CM-NEXT: EXP_IEEE * T0.W (MASKED), T1.W, +; CM-NEXT: ADD_INT T2.X, T0.Z, literal.x, +; CM-NEXT: MULADD_IEEE T2.Y, T1.Z, literal.y, T2.Z, BS:VEC_102/SCL_221 +; CM-NEXT: ADD T1.Z, T1.Y, -T0.W, +; CM-NEXT: MUL_IEEE * T0.W, PV.X, literal.z, +; CM-NEXT: 102(1.429324e-43), 967029397(3.122284e-04) +; CM-NEXT: 2130706432(1.701412e+38), 0(0.000000e+00) +; CM-NEXT: SETGT_UINT T4.X, T0.Z, literal.x, +; CM-NEXT: MUL_IEEE T1.Y, PV.W, literal.y, +; CM-NEXT: SETGT_UINT T2.Z, T0.Z, literal.z, +; CM-NEXT: ADD * T1.W, PV.Z, PV.Y, +; CM-NEXT: -229(nan), 2130706432(1.701412e+38) +; CM-NEXT: 254(3.559298e-43), 0(0.000000e+00) ; CM-NEXT: EXP_IEEE T1.X (MASKED), T1.W, -; CM-NEXT: EXP_IEEE T1.Y, T1.W, -; CM-NEXT: EXP_IEEE T1.Z (MASKED), T1.W, +; CM-NEXT: EXP_IEEE T1.Y (MASKED), T1.W, +; CM-NEXT: EXP_IEEE T1.Z, T1.W, ; CM-NEXT: EXP_IEEE * T1.W (MASKED), T1.W, -; CM-NEXT: FLT_TO_INT T2.X, T1.Z, -; CM-NEXT: MUL_IEEE T2.Y, PV.Y, literal.x, -; CM-NEXT: CNDE_INT T1.Z, T3.Y, T3.X, T0.W, -; CM-NEXT: SETGT_INT * T0.W, T0.Z, literal.y, BS:VEC_120/SCL_212 -; CM-NEXT: 209715200(1.972152e-31), -127(nan) -; CM-NEXT: CNDE_INT T3.X, PV.W, PV.Z, T0.Y, -; CM-NEXT: MUL_IEEE * T4.Y, PV.Y, literal.x, -; CM-NEXT: 209715200(1.972152e-31), 0(0.000000e+00) -; CM-NEXT: ALU clause starting at 108: -; CM-NEXT: SETGT_UINT T1.Z, T2.X, literal.x, -; CM-NEXT: MAX_INT * T1.W, T0.Z, literal.y, -; CM-NEXT: -229(nan), -330(nan) -; CM-NEXT: ADD_INT T4.X, PV.W, literal.x, -; CM-NEXT: ADD_INT T5.Y, T0.Z, literal.y, -; CM-NEXT: CNDE_INT T2.Z, PV.Z, T4.Y, T2.Y, -; CM-NEXT: SETGT_INT * T1.W, T2.X, literal.z, +; CM-NEXT: ALU clause starting at 109: +; CM-NEXT: CNDE_INT T5.X, T2.Z, T0.W, T1.Y, +; CM-NEXT: CNDE_INT T1.Y, T4.X, T3.Y, T2.X, +; CM-NEXT: FLT_TO_INT T3.Z, T3.X, BS:VEC_120/SCL_212 +; CM-NEXT: MUL_IEEE * T0.W, T1.Z, literal.x, BS:VEC_120/SCL_212 +; CM-NEXT: 2130706432(1.701412e+38), 0(0.000000e+00) +; CM-NEXT: SETGT_INT T2.X, T0.Z, literal.x, +; CM-NEXT: MUL_IEEE T2.Y, T0.X, literal.y, +; CM-NEXT: MUL_IEEE T4.Z, PV.W, literal.z, +; CM-NEXT: SETGT_UINT * T1.W, PV.Z, literal.w, +; CM-NEXT: -127(nan), 209715200(1.972152e-31) +; CM-NEXT: 2130706432(1.701412e+38), 254(3.559298e-43) +; CM-NEXT: CNDE_INT T3.X, PV.W, T0.W, PV.Z, +; CM-NEXT: MUL_IEEE T3.Y, PV.Y, literal.x, +; CM-NEXT: CNDE_INT T4.Z, PV.X, T1.Y, T0.Z, +; CM-NEXT: MAX_INT * T0.W, T3.Z, literal.y, +; CM-NEXT: 209715200(1.972152e-31), -330(nan) +; CM-NEXT: ADD_INT T6.X, PV.W, literal.x, +; CM-NEXT: ADD_INT T1.Y, T3.Z, literal.y, +; CM-NEXT: SETGT_UINT T5.Z, T3.Z, literal.z, +; CM-NEXT: MUL_IEEE * T0.W, T1.Z, literal.w, BS:VEC_120/SCL_212 ; CM-NEXT: 204(2.858649e-43), 102(1.429324e-43) +; CM-NEXT: -229(nan), 209715200(1.972152e-31) +; CM-NEXT: MUL_IEEE T7.X, PV.W, literal.x, +; CM-NEXT: MIN_INT T4.Y, T3.Z, literal.y, +; CM-NEXT: CNDE_INT T6.Z, PV.Z, PV.X, PV.Y, +; CM-NEXT: SETGT_INT * T2.W, T3.Z, literal.z, +; CM-NEXT: 209715200(1.972152e-31), 381(5.338947e-43) ; CM-NEXT: -127(nan), 0(0.000000e+00) -; CM-NEXT: CNDE_INT T5.X, PV.W, PV.Z, T1.Y, -; CM-NEXT: MUL_IEEE T0.Y, T0.Y, literal.x, -; CM-NEXT: MAX_INT T2.Z, T2.X, literal.y, -; CM-NEXT: CNDE_INT * T2.W, T3.Y, PV.X, PV.Y, BS:VEC_120/SCL_212 -; CM-NEXT: 2130706432(1.701412e+38), -330(nan) -; CM-NEXT: CNDE_INT T4.X, T0.W, PV.W, T0.Z, -; CM-NEXT: ADD_INT T2.Y, PV.Z, literal.x, -; CM-NEXT: ADD_INT T2.Z, T2.X, literal.y, -; CM-NEXT: MIN_INT * T0.W, T2.X, literal.z, -; CM-NEXT: 204(2.858649e-43), 102(1.429324e-43) -; CM-NEXT: 381(5.338947e-43), 0(0.000000e+00) -; CM-NEXT: ADD_INT T6.X, PV.W, literal.x, -; CM-NEXT: ADD_INT T3.Y, T2.X, literal.y, -; CM-NEXT: SETGT_UINT T3.Z, T2.X, literal.z, -; CM-NEXT: CNDE_INT * T0.W, T1.Z, PV.Y, PV.Z, -; CM-NEXT: -254(nan), -127(nan) -; CM-NEXT: 254(3.559298e-43), 0(0.000000e+00) -; CM-NEXT: MUL_IEEE T7.X, T1.Y, literal.x, -; CM-NEXT: CNDE_INT T1.Y, T1.W, PV.W, T2.X, -; CM-NEXT: CNDE_INT T1.Z, PV.Z, PV.Y, PV.X, -; CM-NEXT: MIN_INT * T0.W, T0.Z, literal.y, -; CM-NEXT: 2130706432(1.701412e+38), 381(5.338947e-43) -; CM-NEXT: SETGT_INT T2.X, T2.X, literal.x, -; CM-NEXT: ADD_INT T2.Y, PV.W, literal.y, -; CM-NEXT: ADD_INT T2.Z, T0.Z, literal.z, -; CM-NEXT: SETGT_UINT * T0.W, T0.Z, literal.w, +; CM-NEXT: CNDE_INT T6.X, PV.W, PV.Z, T3.Z, +; CM-NEXT: MIN_INT T1.Y, T0.Z, literal.x, +; CM-NEXT: ADD_INT T6.Z, PV.Y, literal.y, +; CM-NEXT: ADD_INT * T3.W, T3.Z, literal.z, BS:VEC_120/SCL_212 +; CM-NEXT: 381(5.338947e-43), -254(nan) +; CM-NEXT: -127(nan), 0(0.000000e+00) +; CM-NEXT: CNDE_INT T8.X, T1.W, PV.W, PV.Z, +; CM-NEXT: SETGT_INT T4.Y, T3.Z, literal.x, +; CM-NEXT: ADD_INT T3.Z, PV.Y, literal.y, +; CM-NEXT: ADD_INT * T1.W, T0.Z, literal.z, BS:VEC_120/SCL_212 ; CM-NEXT: 127(1.779649e-43), -254(nan) -; CM-NEXT: -127(nan), 254(3.559298e-43) -; CM-NEXT: CNDE_INT T6.X, PV.W, PV.Z, PV.Y, -; CM-NEXT: SETGT_INT T2.Y, T0.Z, literal.x, -; CM-NEXT: CNDE_INT T0.Z, PV.X, T1.Y, T1.Z, -; CM-NEXT: MUL_IEEE * T1.W, T7.X, literal.y, -; CM-NEXT: 127(1.779649e-43), 2130706432(1.701412e+38) -; CM-NEXT: CNDE_INT T7.X, T3.Z, T7.X, PV.W, -; CM-NEXT: LSHL T1.Y, PV.Z, literal.x, -; CM-NEXT: CNDE_INT T0.Z, PV.Y, T4.X, PV.X, BS:VEC_021/SCL_122 -; CM-NEXT: MUL_IEEE * T1.W, T0.Y, literal.y, -; CM-NEXT: 23(3.222986e-44), 2130706432(1.701412e+38) -; CM-NEXT: CNDE_INT T4.X, T0.W, T0.Y, PV.W, -; CM-NEXT: LSHL T0.Y, PV.Z, literal.x, +; CM-NEXT: -127(nan), 0(0.000000e+00) +; CM-NEXT: CNDE_INT T9.X, T2.Z, PV.W, PV.Z, +; CM-NEXT: SETGT_INT T1.Y, T0.Z, literal.x, BS:VEC_120/SCL_212 +; CM-NEXT: CNDE_INT T0.Z, PV.Y, T6.X, PV.X, +; CM-NEXT: CNDE_INT * T0.W, T5.Z, T7.X, T0.W, BS:VEC_201 +; CM-NEXT: 127(1.779649e-43), 0(0.000000e+00) +; CM-NEXT: CNDE_INT T6.X, T2.W, PV.W, T1.Z, +; CM-NEXT: LSHL T5.Y, PV.Z, literal.x, +; CM-NEXT: CNDE_INT T0.Z, PV.Y, T4.Z, PV.X, +; CM-NEXT: CNDE_INT * T0.W, T4.X, T3.Y, T2.Y, +; CM-NEXT: 23(3.222986e-44), 0(0.000000e+00) +; CM-NEXT: CNDE_INT T0.X, T2.X, PV.W, T0.X, +; CM-NEXT: LSHL T2.Y, PV.Z, literal.x, ; CM-NEXT: ADD_INT T0.Z, PV.Y, literal.y, -; CM-NEXT: CNDE_INT * T0.W, T2.X, T5.X, PV.X, +; CM-NEXT: CNDE_INT * T0.W, T4.Y, PV.X, T3.X, BS:VEC_021/SCL_122 ; CM-NEXT: 23(3.222986e-44), 1065353216(1.000000e+00) ; CM-NEXT: MUL_IEEE T2.X, PV.W, PV.Z, -; CM-NEXT: SETGT T1.Y, literal.x, KC0[3].W, +; CM-NEXT: SETGT T3.Y, literal.x, KC0[3].W, ; CM-NEXT: ADD_INT T0.Z, PV.Y, literal.y, -; CM-NEXT: CNDE_INT * T0.W, T2.Y, T3.X, PV.X, +; CM-NEXT: CNDE_INT * T0.W, T1.Y, PV.X, T5.X, ; CM-NEXT: -1026650416(-1.032789e+02), 1065353216(1.000000e+00) -; CM-NEXT: MUL_IEEE T3.X, PV.W, PV.Z, -; CM-NEXT: SETGT T0.Y, literal.x, KC0[3].Z, +; CM-NEXT: MUL_IEEE T0.X, PV.W, PV.Z, +; CM-NEXT: SETGT T1.Y, literal.x, KC0[3].Z, ; CM-NEXT: CNDE T0.Z, PV.Y, PV.X, 0.0, ; CM-NEXT: SETGT * T0.W, KC0[3].W, literal.y, ; CM-NEXT: -1026650416(-1.032789e+02), 1118925336(8.872284e+01) ; CM-NEXT: CNDE T2.X, PV.W, PV.Z, literal.x, -; CM-NEXT: CNDE T0.Y, PV.Y, PV.X, 0.0, +; CM-NEXT: CNDE T1.Y, PV.Y, PV.X, 0.0, ; CM-NEXT: SETGT T0.Z, KC0[3].Z, literal.y, ; CM-NEXT: ADD_INT * T0.W, KC0[2].Y, literal.z, ; CM-NEXT: 2139095040(INF), 1118925336(8.872284e+01) ; CM-NEXT: 8(1.121039e-44), 0(0.000000e+00) -; CM-NEXT: LSHR T3.X, PV.W, literal.x, -; CM-NEXT: CNDE T0.Y, PV.Z, PV.Y, literal.y, -; CM-NEXT: CNDE T0.Z, T1.X, T0.X, 0.0, +; CM-NEXT: LSHR T0.X, PV.W, literal.x, +; CM-NEXT: CNDE T1.Y, PV.Z, PV.Y, literal.y, +; CM-NEXT: CNDE T0.Z, T1.X, T0.Y, 0.0, ; CM-NEXT: SETGT * T0.W, KC0[3].Y, literal.z, ; CM-NEXT: 2(2.802597e-45), 2139095040(INF) ; CM-NEXT: 1118925336(8.872284e+01), 0(0.000000e+00) -; CM-NEXT: CNDE * T0.X, PV.W, PV.Z, literal.x, +; CM-NEXT: CNDE * T1.X, PV.W, PV.Z, literal.x, ; CM-NEXT: 2139095040(INF), 0(0.000000e+00) -; CM-NEXT: LSHR * T1.X, KC0[2].Y, literal.x, +; CM-NEXT: LSHR * T3.X, KC0[2].Y, literal.x, ; CM-NEXT: 2(2.802597e-45), 0(0.000000e+00) %result = call <3 x float> @llvm.exp.v3f32(<3 x float> %in) store <3 x float> %result, ptr addrspace(1) %out @@ -2041,224 +2050,227 @@ define amdgpu_kernel void @s_exp_v4f32(ptr addrspace(1) %out, <4 x float> %in) { ; R600-LABEL: s_exp_v4f32: ; R600: ; %bb.0: ; R600-NEXT: ALU 98, @6, KC0[CB0:0-32], KC1[] -; R600-NEXT: ALU 95, @105, KC0[CB0:0-32], KC1[] -; R600-NEXT: ALU 24, @201, KC0[CB0:0-32], KC1[] +; R600-NEXT: ALU 98, @105, KC0[CB0:0-32], KC1[] +; R600-NEXT: ALU 24, @204, KC0[CB0:0-32], KC1[] ; R600-NEXT: MEM_RAT_CACHELESS STORE_RAW T1.XYZW, T0.X, 1 ; R600-NEXT: CF_END ; R600-NEXT: PAD ; R600-NEXT: ALU clause starting at 6: ; R600-NEXT: AND_INT * T0.W, KC0[3].Z, literal.x, ; R600-NEXT: -4096(nan), 0(0.000000e+00) -; R600-NEXT: ADD * T1.W, KC0[3].Z, -PV.W, -; R600-NEXT: MUL_IEEE T2.W, PV.W, literal.x, -; R600-NEXT: MUL_IEEE * T3.W, T0.W, literal.y, -; R600-NEXT: 967029397(3.122284e-04), 1069064192(1.442383e+00) -; R600-NEXT: RNDNE T4.W, PS, -; R600-NEXT: MULADD_IEEE * T1.W, T1.W, literal.x, PV.W, BS:VEC_021/SCL_122 +; R600-NEXT: ADD T1.W, KC0[3].Z, -PV.W, +; R600-NEXT: MUL_IEEE * T2.W, PV.W, literal.x, ; R600-NEXT: 1069064192(1.442383e+00), 0(0.000000e+00) -; R600-NEXT: MULADD_IEEE T0.W, T0.W, literal.x, PS, -; R600-NEXT: ADD * T1.W, T3.W, -PV.W, +; R600-NEXT: RNDNE T3.W, PS, +; R600-NEXT: MUL_IEEE * T4.W, PV.W, literal.x, ; R600-NEXT: 967029397(3.122284e-04), 0(0.000000e+00) -; R600-NEXT: ADD T0.W, PS, PV.W, -; R600-NEXT: TRUNC * T1.W, T4.W, -; R600-NEXT: FLT_TO_INT T1.W, PS, -; R600-NEXT: EXP_IEEE * T0.X, PV.W, -; R600-NEXT: MUL_IEEE T0.Z, PS, literal.x, -; R600-NEXT: MAX_INT T0.W, PV.W, literal.y, -; R600-NEXT: MIN_INT * T2.W, PV.W, literal.z, -; R600-NEXT: 209715200(1.972152e-31), -330(nan) +; R600-NEXT: MULADD_IEEE T1.W, T1.W, literal.x, PS, +; R600-NEXT: TRUNC * T4.W, PV.W, +; R600-NEXT: 1069064192(1.442383e+00), 0(0.000000e+00) +; R600-NEXT: FLT_TO_INT T0.Z, PS, +; R600-NEXT: MULADD_IEEE T0.W, T0.W, literal.x, PV.W, +; R600-NEXT: ADD * T1.W, T2.W, -T3.W, +; R600-NEXT: 967029397(3.122284e-04), 0(0.000000e+00) +; R600-NEXT: ADD T1.Z, PS, PV.W, +; R600-NEXT: MAX_INT T0.W, PV.Z, literal.x, +; R600-NEXT: MIN_INT * T1.W, PV.Z, literal.y, +; R600-NEXT: -330(nan), 381(5.338947e-43) +; R600-NEXT: ADD_INT T0.X, PS, literal.x, +; R600-NEXT: ADD_INT T0.Y, PV.W, literal.y, +; R600-NEXT: ADD_INT T2.Z, T0.Z, literal.z, +; R600-NEXT: SETGT_UINT T0.W, T0.Z, literal.w, +; R600-NEXT: EXP_IEEE * T1.X, PV.Z, +; R600-NEXT: -254(nan), 204(2.858649e-43) +; R600-NEXT: 102(1.429324e-43), -229(nan) +; R600-NEXT: ADD_INT T2.X, T0.Z, literal.x, +; R600-NEXT: SETGT_UINT T1.Y, T0.Z, literal.y, +; R600-NEXT: CNDE_INT T1.Z, PV.W, PV.Y, PV.Z, +; R600-NEXT: SETGT_INT T1.W, T0.Z, literal.x, +; R600-NEXT: MUL_IEEE * T2.W, PS, literal.z, +; R600-NEXT: -127(nan), 254(3.559298e-43) +; R600-NEXT: 209715200(1.972152e-31), 0(0.000000e+00) +; R600-NEXT: MUL_IEEE T3.X, T1.X, literal.x, +; R600-NEXT: MUL_IEEE T0.Y, PS, literal.y, +; R600-NEXT: CNDE_INT T1.Z, PV.W, PV.Z, T0.Z, +; R600-NEXT: CNDE_INT T3.W, PV.Y, PV.X, T0.X, +; R600-NEXT: SETGT_INT * T4.W, T0.Z, literal.z, +; R600-NEXT: 2130706432(1.701412e+38), 209715200(1.972152e-31) +; R600-NEXT: 127(1.779649e-43), 0(0.000000e+00) +; R600-NEXT: AND_INT T2.Y, KC0[4].X, literal.x, +; R600-NEXT: CNDE_INT T0.Z, PS, PV.Z, PV.W, +; R600-NEXT: CNDE_INT T0.W, T0.W, PV.Y, T2.W, +; R600-NEXT: MUL_IEEE * T2.W, PV.X, literal.y, +; R600-NEXT: -4096(nan), 2130706432(1.701412e+38) +; R600-NEXT: CNDE_INT T0.X, T1.Y, T3.X, PS, +; R600-NEXT: CNDE_INT T0.Y, T1.W, PV.W, T1.X, +; R600-NEXT: LSHL T0.Z, PV.Z, literal.x, +; R600-NEXT: ADD T0.W, KC0[4].X, -PV.Y, +; R600-NEXT: MUL_IEEE * T1.W, PV.Y, literal.y, +; R600-NEXT: 23(3.222986e-44), 1069064192(1.442383e+00) +; R600-NEXT: RNDNE T1.Y, PS, +; R600-NEXT: MUL_IEEE T1.Z, PV.W, literal.x, +; R600-NEXT: ADD_INT T2.W, PV.Z, literal.y, +; R600-NEXT: CNDE_INT * T3.W, T4.W, PV.Y, PV.X, +; R600-NEXT: 967029397(3.122284e-04), 1065353216(1.000000e+00) +; R600-NEXT: MUL_IEEE T0.Y, PS, PV.W, +; R600-NEXT: AND_INT T0.Z, KC0[3].W, literal.x, +; R600-NEXT: MULADD_IEEE T0.W, T0.W, literal.y, PV.Z, +; R600-NEXT: TRUNC * T2.W, PV.Y, +; R600-NEXT: -4096(nan), 1069064192(1.442383e+00) +; R600-NEXT: SETGT T0.X, literal.x, KC0[3].Z, +; R600-NEXT: FLT_TO_INT T3.Y, PS, +; R600-NEXT: MULADD_IEEE T1.Z, T2.Y, literal.y, PV.W, +; R600-NEXT: ADD T0.W, T1.W, -T1.Y, +; R600-NEXT: MUL_IEEE * T1.W, PV.Z, literal.z, +; R600-NEXT: -1026650416(-1.032789e+02), 967029397(3.122284e-04) +; R600-NEXT: 1069064192(1.442383e+00), 0(0.000000e+00) +; R600-NEXT: RNDNE T1.X, PS, +; R600-NEXT: AND_INT T1.Y, KC0[3].Y, literal.x, +; R600-NEXT: ADD T1.Z, PV.W, PV.Z, +; R600-NEXT: MAX_INT T0.W, PV.Y, literal.y, +; R600-NEXT: MIN_INT * T2.W, PV.Y, literal.z, +; R600-NEXT: -4096(nan), -330(nan) ; R600-NEXT: 381(5.338947e-43), 0(0.000000e+00) -; R600-NEXT: ADD_INT T1.X, PS, literal.x, -; R600-NEXT: AND_INT T0.Y, KC0[4].X, literal.y, -; R600-NEXT: ADD_INT T1.Z, PV.W, literal.z, -; R600-NEXT: ADD_INT * T0.W, T1.W, literal.w, -; R600-NEXT: -254(nan), -4096(nan) -; R600-NEXT: 204(2.858649e-43), 102(1.429324e-43) -; R600-NEXT: SETGT_UINT * T2.W, T1.W, literal.x, -; R600-NEXT: -229(nan), 0(0.000000e+00) -; R600-NEXT: ADD_INT T2.X, T1.W, literal.x, -; R600-NEXT: SETGT_UINT T1.Y, T1.W, literal.y, -; R600-NEXT: CNDE_INT T1.Z, PV.W, T1.Z, T0.W, -; R600-NEXT: SETGT_INT T0.W, T1.W, literal.x, -; R600-NEXT: ADD * T3.W, KC0[4].X, -T0.Y, +; R600-NEXT: ADD_INT T2.X, PS, literal.x, +; R600-NEXT: ADD_INT T2.Y, PV.W, literal.y, +; R600-NEXT: ADD_INT T2.Z, T3.Y, literal.z, +; R600-NEXT: SETGT_UINT T0.W, T3.Y, literal.w, +; R600-NEXT: EXP_IEEE * T1.Z, PV.Z, +; R600-NEXT: -254(nan), 204(2.858649e-43) +; R600-NEXT: 102(1.429324e-43), -229(nan) +; R600-NEXT: ADD_INT T3.X, T3.Y, literal.x, +; R600-NEXT: SETGT_UINT T4.Y, T3.Y, literal.y, +; R600-NEXT: CNDE_INT T2.Z, PV.W, PV.Y, PV.Z, +; R600-NEXT: SETGT_INT T2.W, T3.Y, literal.x, +; R600-NEXT: MUL_IEEE * T3.W, PS, literal.z, ; R600-NEXT: -127(nan), 254(3.559298e-43) -; R600-NEXT: MUL_IEEE T3.X, PS, literal.x, -; R600-NEXT: MUL_IEEE T2.Y, T0.Y, literal.y, -; R600-NEXT: CNDE_INT T1.Z, PV.W, PV.Z, T1.W, -; R600-NEXT: CNDE_INT T4.W, PV.Y, PV.X, T1.X, -; R600-NEXT: SETGT_INT * T1.W, T1.W, literal.z, -; R600-NEXT: 967029397(3.122284e-04), 1069064192(1.442383e+00) +; R600-NEXT: 209715200(1.972152e-31), 0(0.000000e+00) +; R600-NEXT: MUL_IEEE T4.X, T1.Z, literal.x, +; R600-NEXT: MUL_IEEE T2.Y, PS, literal.y, +; R600-NEXT: CNDE_INT T2.Z, PV.W, PV.Z, T3.Y, +; R600-NEXT: CNDE_INT T4.W, PV.Y, PV.X, T2.X, +; R600-NEXT: SETGT_INT * T5.W, T3.Y, literal.z, +; R600-NEXT: 2130706432(1.701412e+38), 209715200(1.972152e-31) ; R600-NEXT: 127(1.779649e-43), 0(0.000000e+00) -; R600-NEXT: CNDE_INT T1.X, PS, PV.Z, PV.W, -; R600-NEXT: RNDNE T3.Y, PV.Y, -; R600-NEXT: MULADD_IEEE T1.Z, T3.W, literal.x, PV.X, -; R600-NEXT: MUL_IEEE T3.W, T0.Z, literal.y, -; R600-NEXT: MUL_IEEE * T4.W, T0.X, literal.z, -; R600-NEXT: 1069064192(1.442383e+00), 209715200(1.972152e-31) +; R600-NEXT: ADD T2.X, KC0[3].W, -T0.Z, +; R600-NEXT: CNDE_INT T3.Y, PS, PV.Z, PV.W, +; R600-NEXT: CNDE_INT * T2.Z, T0.W, PV.Y, T3.W, +; R600-NEXT: ALU clause starting at 105: +; R600-NEXT: MUL_IEEE T0.W, T4.X, literal.x, +; R600-NEXT: ADD * T3.W, KC0[3].Y, -T1.Y, ; R600-NEXT: 2130706432(1.701412e+38), 0(0.000000e+00) -; R600-NEXT: MUL_IEEE T2.X, PS, literal.x, -; R600-NEXT: CNDE_INT T4.Y, T2.W, PV.W, T0.Z, -; R600-NEXT: MULADD_IEEE T0.Z, T0.Y, literal.y, PV.Z, -; R600-NEXT: ADD T2.W, T2.Y, -PV.Y, BS:VEC_120/SCL_212 -; R600-NEXT: AND_INT * T3.W, KC0[3].Y, literal.z, -; R600-NEXT: 2130706432(1.701412e+38), 967029397(3.122284e-04) -; R600-NEXT: -4096(nan), 0(0.000000e+00) ; R600-NEXT: MUL_IEEE T3.X, PS, literal.x, -; R600-NEXT: ADD T0.Y, PV.W, PV.Z, -; R600-NEXT: CNDE_INT T0.Z, T0.W, PV.Y, T0.X, BS:VEC_021/SCL_122 -; R600-NEXT: CNDE_INT T0.W, T1.Y, T4.W, PV.X, -; R600-NEXT: LSHL * T2.W, T1.X, literal.y, -; R600-NEXT: 1069064192(1.442383e+00), 23(3.222986e-44) -; R600-NEXT: AND_INT T0.X, KC0[3].W, literal.x, -; R600-NEXT: TRUNC T1.Y, T3.Y, -; R600-NEXT: ADD_INT T1.Z, PS, literal.y, -; R600-NEXT: CNDE_INT T0.W, T1.W, PV.Z, PV.W, -; R600-NEXT: EXP_IEEE * T0.Y, PV.Y, -; R600-NEXT: -4096(nan), 1065353216(1.000000e+00) -; R600-NEXT: MUL_IEEE T1.X, PV.W, PV.Z, -; R600-NEXT: FLT_TO_INT T1.Y, PV.Y, -; R600-NEXT: MUL_IEEE T0.Z, PS, literal.x, -; R600-NEXT: ADD T0.W, KC0[3].W, -PV.X, -; R600-NEXT: RNDNE * T1.W, T3.X, -; R600-NEXT: 209715200(1.972152e-31), 0(0.000000e+00) -; R600-NEXT: SETGT T2.X, literal.x, KC0[3].Z, -; R600-NEXT: TRUNC T2.Y, PS, -; R600-NEXT: MUL_IEEE T1.Z, PV.W, literal.y, -; R600-NEXT: MUL_IEEE T2.W, PV.Z, literal.z, -; R600-NEXT: MAX_INT * T4.W, PV.Y, literal.w, -; R600-NEXT: -1026650416(-1.032789e+02), 967029397(3.122284e-04) -; R600-NEXT: 209715200(1.972152e-31), -330(nan) -; R600-NEXT: ADD T4.X, KC0[3].Y, -T3.W, -; R600-NEXT: ADD_INT T3.Y, PS, literal.x, -; R600-NEXT: ADD_INT T2.Z, T1.Y, literal.y, -; R600-NEXT: SETGT_UINT T4.W, T1.Y, literal.z, -; R600-NEXT: MIN_INT * T5.W, T1.Y, literal.w, -; R600-NEXT: 204(2.858649e-43), 102(1.429324e-43) -; R600-NEXT: -229(nan), 381(5.338947e-43) -; R600-NEXT: ADD_INT T5.X, PS, literal.x, -; R600-NEXT: ADD_INT T4.Y, T1.Y, literal.y, -; R600-NEXT: SETGT_UINT T3.Z, T1.Y, literal.z, -; R600-NEXT: CNDE_INT T5.W, PV.W, PV.Y, PV.Z, -; R600-NEXT: SETGT_INT * T6.W, T1.Y, literal.y, -; R600-NEXT: -254(nan), -127(nan) -; R600-NEXT: 254(3.559298e-43), 0(0.000000e+00) -; R600-NEXT: MUL_IEEE T6.X, T0.Y, literal.x, -; R600-NEXT: CNDE_INT T3.Y, PS, PV.W, T1.Y, -; R600-NEXT: CNDE_INT * T2.Z, PV.Z, PV.Y, PV.X, -; R600-NEXT: 2130706432(1.701412e+38), 0(0.000000e+00) -; R600-NEXT: ALU clause starting at 105: -; R600-NEXT: SETGT_INT T5.W, T1.Y, literal.x, -; R600-NEXT: MUL_IEEE * T7.W, T4.X, literal.y, -; R600-NEXT: 127(1.779649e-43), 967029397(3.122284e-04) -; R600-NEXT: MUL_IEEE T5.X, T0.X, literal.x, -; R600-NEXT: MULADD_IEEE T1.Y, T4.X, literal.x, PS, BS:VEC_120/SCL_212 -; R600-NEXT: CNDE_INT T2.Z, PV.W, T3.Y, T2.Z, -; R600-NEXT: MUL_IEEE T7.W, T6.X, literal.y, BS:VEC_201 -; R600-NEXT: CNDE_INT * T2.W, T4.W, T2.W, T0.Z, -; R600-NEXT: 1069064192(1.442383e+00), 2130706432(1.701412e+38) -; R600-NEXT: CNDE_INT T4.X, T6.W, PS, T0.Y, -; R600-NEXT: CNDE_INT T0.Y, T3.Z, T6.X, PV.W, -; R600-NEXT: LSHL T0.Z, PV.Z, literal.x, -; R600-NEXT: MULADD_IEEE T2.W, T3.W, literal.y, PV.Y, BS:VEC_201 -; R600-NEXT: ADD * T1.W, T3.X, -T1.W, -; R600-NEXT: 23(3.222986e-44), 967029397(3.122284e-04) -; R600-NEXT: ADD T3.X, PS, PV.W, -; R600-NEXT: ADD_INT T1.Y, PV.Z, literal.x, -; R600-NEXT: CNDE_INT T0.Z, T5.W, PV.X, PV.Y, -; R600-NEXT: RNDNE T1.W, T5.X, -; R600-NEXT: MULADD_IEEE * T0.W, T0.W, literal.y, T1.Z, BS:VEC_021/SCL_122 +; R600-NEXT: MUL_IEEE T2.Y, T1.Y, literal.y, +; R600-NEXT: CNDE_INT T3.Z, T4.Y, T4.X, PV.W, BS:VEC_120/SCL_212 +; R600-NEXT: CNDE_INT T0.W, T2.W, T2.Z, T1.Z, +; R600-NEXT: LSHL * T2.W, T3.Y, literal.z, +; R600-NEXT: 967029397(3.122284e-04), 1069064192(1.442383e+00) +; R600-NEXT: 23(3.222986e-44), 0(0.000000e+00) +; R600-NEXT: ADD_INT T4.X, PS, literal.x, +; R600-NEXT: CNDE_INT T3.Y, T5.W, PV.W, PV.Z, +; R600-NEXT: RNDNE T1.Z, PV.Y, +; R600-NEXT: MULADD_IEEE T0.W, T3.W, literal.y, PV.X, BS:VEC_120/SCL_212 +; R600-NEXT: MUL_IEEE * T2.W, T2.X, literal.z, ; R600-NEXT: 1065353216(1.000000e+00), 1069064192(1.442383e+00) -; R600-NEXT: MULADD_IEEE T0.X, T0.X, literal.x, PS, -; R600-NEXT: ADD T0.Y, T5.X, -PV.W, BS:VEC_120/SCL_212 -; R600-NEXT: MUL_IEEE T0.Z, PV.Z, PV.Y, -; R600-NEXT: SETGT T0.W, literal.y, KC0[4].X, -; R600-NEXT: EXP_IEEE * T1.Y, PV.X, -; R600-NEXT: 967029397(3.122284e-04), -1026650416(-1.032789e+02) -; R600-NEXT: CNDE T3.X, PV.W, PV.Z, 0.0, -; R600-NEXT: ADD T0.Y, PV.Y, PV.X, -; R600-NEXT: FLT_TO_INT T0.Z, T2.Y, -; R600-NEXT: TRUNC T0.W, T1.W, -; R600-NEXT: MUL_IEEE * T1.W, PS, literal.x, +; R600-NEXT: 967029397(3.122284e-04), 0(0.000000e+00) +; R600-NEXT: MULADD_IEEE T2.X, T2.X, literal.x, PS, +; R600-NEXT: MULADD_IEEE T1.Y, T1.Y, literal.y, PV.W, +; R600-NEXT: ADD T2.Z, T2.Y, -PV.Z, BS:VEC_120/SCL_212 +; R600-NEXT: MUL_IEEE T0.W, PV.Y, PV.X, +; R600-NEXT: SETGT * T2.W, literal.z, KC0[4].X, +; R600-NEXT: 1069064192(1.442383e+00), 967029397(3.122284e-04) +; R600-NEXT: -1026650416(-1.032789e+02), 0(0.000000e+00) +; R600-NEXT: CNDE T3.X, PS, PV.W, 0.0, +; R600-NEXT: ADD T1.Y, PV.Z, PV.Y, +; R600-NEXT: TRUNC T1.Z, T1.Z, +; R600-NEXT: MULADD_IEEE T0.W, T0.Z, literal.x, PV.X, BS:VEC_120/SCL_212 +; R600-NEXT: ADD * T1.W, T1.W, -T1.X, +; R600-NEXT: 967029397(3.122284e-04), 0(0.000000e+00) +; R600-NEXT: SETGT T2.X, KC0[4].X, literal.x, +; R600-NEXT: ADD T2.Y, PS, PV.W, +; R600-NEXT: FLT_TO_INT T0.Z, PV.Z, +; R600-NEXT: TRUNC T0.W, T1.X, +; R600-NEXT: EXP_IEEE * T1.X, PV.Y, +; R600-NEXT: 1118925336(8.872284e+01), 0(0.000000e+00) +; R600-NEXT: MUL_IEEE T4.X, PS, literal.x, +; R600-NEXT: FLT_TO_INT T1.Y, PV.W, +; R600-NEXT: MAX_INT T1.Z, PV.Z, literal.y, +; R600-NEXT: MUL_IEEE T0.W, PS, literal.z, +; R600-NEXT: EXP_IEEE * T1.W, PV.Y, +; R600-NEXT: 2130706432(1.701412e+38), -330(nan) ; R600-NEXT: 209715200(1.972152e-31), 0(0.000000e+00) -; R600-NEXT: SETGT T0.X, KC0[4].X, literal.x, -; R600-NEXT: MUL_IEEE T2.Y, PS, literal.y, -; R600-NEXT: FLT_TO_INT T1.Z, PV.W, -; R600-NEXT: MAX_INT T0.W, PV.Z, literal.z, -; R600-NEXT: EXP_IEEE * T0.Y, PV.Y, -; R600-NEXT: 1118925336(8.872284e+01), 209715200(1.972152e-31) -; R600-NEXT: -330(nan), 0(0.000000e+00) -; R600-NEXT: MUL_IEEE T4.X, T1.Y, literal.x, -; R600-NEXT: MUL_IEEE T3.Y, PS, literal.y, -; R600-NEXT: ADD_INT T2.Z, PV.W, literal.z, -; R600-NEXT: ADD_INT * T0.W, T0.Z, literal.w, -; R600-NEXT: 2130706432(1.701412e+38), 209715200(1.972152e-31) -; R600-NEXT: 204(2.858649e-43), 102(1.429324e-43) -; R600-NEXT: MAX_INT * T2.W, T1.Z, literal.x, -; R600-NEXT: -330(nan), 0(0.000000e+00) -; R600-NEXT: SETGT_UINT T5.X, T0.Z, literal.x, -; R600-NEXT: ADD_INT T4.Y, PV.W, literal.y, -; R600-NEXT: ADD_INT T3.Z, T1.Z, literal.z, BS:VEC_120/SCL_212 -; R600-NEXT: SETGT_UINT T2.W, T1.Z, literal.x, BS:VEC_120/SCL_212 -; R600-NEXT: MIN_INT * T3.W, T1.Z, literal.w, +; R600-NEXT: MUL_IEEE T5.X, PV.W, literal.x, +; R600-NEXT: MUL_IEEE T2.Y, PS, literal.x, +; R600-NEXT: ADD_INT T1.Z, PV.Z, literal.y, +; R600-NEXT: ADD_INT T2.W, T0.Z, literal.z, +; R600-NEXT: MAX_INT * T3.W, PV.Y, literal.w, +; R600-NEXT: 209715200(1.972152e-31), 204(2.858649e-43) +; R600-NEXT: 102(1.429324e-43), -330(nan) +; R600-NEXT: SETGT_UINT T6.X, T0.Z, literal.x, +; R600-NEXT: ADD_INT T3.Y, PS, literal.y, +; R600-NEXT: ADD_INT T2.Z, T1.Y, literal.z, +; R600-NEXT: SETGT_UINT T3.W, T1.Y, literal.x, +; R600-NEXT: MIN_INT * T4.W, T1.Y, literal.w, ; R600-NEXT: -229(nan), 204(2.858649e-43) ; R600-NEXT: 102(1.429324e-43), 381(5.338947e-43) -; R600-NEXT: ADD_INT T6.X, PS, literal.x, -; R600-NEXT: ADD_INT T5.Y, T1.Z, literal.y, -; R600-NEXT: SETGT_UINT T4.Z, T1.Z, literal.z, -; R600-NEXT: CNDE_INT T3.W, PV.W, PV.Y, PV.Z, -; R600-NEXT: SETGT_INT * T4.W, T1.Z, literal.y, +; R600-NEXT: ADD_INT T7.X, PS, literal.x, +; R600-NEXT: ADD_INT T4.Y, T1.Y, literal.y, +; R600-NEXT: SETGT_UINT T3.Z, T1.Y, literal.z, +; R600-NEXT: CNDE_INT T4.W, PV.W, PV.Y, PV.Z, +; R600-NEXT: SETGT_INT * T5.W, T1.Y, literal.y, ; R600-NEXT: -254(nan), -127(nan) ; R600-NEXT: 254(3.559298e-43), 0(0.000000e+00) -; R600-NEXT: CNDE_INT T7.X, PS, PV.W, T1.Z, BS:VEC_021/SCL_122 -; R600-NEXT: CNDE_INT T4.Y, PV.Z, PV.Y, PV.X, -; R600-NEXT: SETGT_INT T1.Z, T1.Z, literal.x, BS:VEC_120/SCL_212 -; R600-NEXT: CNDE_INT T0.W, T5.X, T2.Z, T0.W, BS:VEC_102/SCL_221 -; R600-NEXT: SETGT_INT * T3.W, T0.Z, literal.y, +; R600-NEXT: CNDE_INT T8.X, PS, PV.W, T1.Y, +; R600-NEXT: CNDE_INT T3.Y, PV.Z, PV.Y, PV.X, +; R600-NEXT: SETGT_INT T2.Z, T1.Y, literal.x, +; R600-NEXT: CNDE_INT T2.W, T6.X, T1.Z, T2.W, +; R600-NEXT: SETGT_INT * T4.W, T0.Z, literal.y, ; R600-NEXT: 127(1.779649e-43), -127(nan) -; R600-NEXT: CNDE_INT T6.X, PS, PV.W, T0.Z, -; R600-NEXT: CNDE_INT T4.Y, PV.Z, PV.X, PV.Y, -; R600-NEXT: MIN_INT T2.Z, T0.Z, literal.x, -; R600-NEXT: MUL_IEEE T0.W, T3.Y, literal.y, -; R600-NEXT: MUL_IEEE * T5.W, T0.Y, literal.z, -; R600-NEXT: 381(5.338947e-43), 209715200(1.972152e-31) -; R600-NEXT: 2130706432(1.701412e+38), 0(0.000000e+00) -; R600-NEXT: MUL_IEEE T7.X, PS, literal.x, -; R600-NEXT: CNDE_INT T3.Y, T2.W, PV.W, T3.Y, -; R600-NEXT: ADD_INT T2.Z, PV.Z, literal.y, -; R600-NEXT: ADD_INT T0.W, T0.Z, literal.z, -; R600-NEXT: SETGT_UINT * T2.W, T0.Z, literal.w, +; R600-NEXT: CNDE_INT T7.X, PS, PV.W, T0.Z, +; R600-NEXT: CNDE_INT T1.Y, PV.Z, PV.X, PV.Y, +; R600-NEXT: MIN_INT T1.Z, T0.Z, literal.x, +; R600-NEXT: MUL_IEEE T2.W, T1.W, literal.y, +; R600-NEXT: MUL_IEEE * T6.W, T2.Y, literal.z, +; R600-NEXT: 381(5.338947e-43), 2130706432(1.701412e+38) +; R600-NEXT: 209715200(1.972152e-31), 0(0.000000e+00) +; R600-NEXT: CNDE_INT T8.X, T3.W, PS, T2.Y, +; R600-NEXT: MUL_IEEE T2.Y, PV.W, literal.x, +; R600-NEXT: ADD_INT T1.Z, PV.Z, literal.y, +; R600-NEXT: ADD_INT T3.W, T0.Z, literal.z, +; R600-NEXT: SETGT_UINT * T6.W, T0.Z, literal.w, ; R600-NEXT: 2130706432(1.701412e+38), -254(nan) ; R600-NEXT: -127(nan), 254(3.559298e-43) -; R600-NEXT: CNDE_INT T8.X, PS, PV.W, PV.Z, -; R600-NEXT: SETGT_INT T5.Y, T0.Z, literal.x, -; R600-NEXT: CNDE_INT T0.Z, T4.W, PV.Y, T0.Y, BS:VEC_021/SCL_122 -; R600-NEXT: CNDE_INT T0.W, T4.Z, T5.W, PV.X, BS:VEC_120/SCL_212 -; R600-NEXT: LSHL * T4.W, T4.Y, literal.y, +; R600-NEXT: CNDE_INT T9.X, PS, PV.W, PV.Z, +; R600-NEXT: SETGT_INT T3.Y, T0.Z, literal.x, +; R600-NEXT: CNDE_INT T0.Z, T3.Z, T2.W, PV.Y, BS:VEC_120/SCL_212 +; R600-NEXT: CNDE_INT T1.W, T5.W, PV.X, T1.W, BS:VEC_021/SCL_122 +; R600-NEXT: LSHL * T2.W, T1.Y, literal.y, ; R600-NEXT: 127(1.779649e-43), 23(3.222986e-44) -; R600-NEXT: ADD_INT T7.X, PS, literal.x, -; R600-NEXT: CNDE_INT T0.Y, T1.Z, PV.Z, PV.W, -; R600-NEXT: CNDE_INT T0.Z, PV.Y, T6.X, PV.X, -; R600-NEXT: MUL_IEEE T0.W, T4.X, literal.y, -; R600-NEXT: CNDE_INT * T1.W, T5.X, T2.Y, T1.W, -; R600-NEXT: 1065353216(1.000000e+00), 2130706432(1.701412e+38) -; R600-NEXT: CNDE_INT T5.X, T3.W, PS, T1.Y, -; R600-NEXT: CNDE_INT * T1.Y, T2.W, T4.X, PV.W, BS:VEC_120/SCL_212 -; R600-NEXT: ALU clause starting at 201: +; R600-NEXT: ADD_INT T8.X, PS, literal.x, +; R600-NEXT: CNDE_INT T1.Y, T2.Z, PV.W, PV.Z, +; R600-NEXT: CNDE_INT T0.Z, PV.Y, T7.X, PV.X, +; R600-NEXT: CNDE_INT * T0.W, T6.X, T5.X, T0.W, BS:VEC_021/SCL_122 +; R600-NEXT: 1065353216(1.000000e+00), 0(0.000000e+00) +; R600-NEXT: MUL_IEEE * T1.W, T4.X, literal.x, +; R600-NEXT: 2130706432(1.701412e+38), 0(0.000000e+00) +; R600-NEXT: CNDE_INT T4.X, T6.W, T4.X, PV.W, +; R600-NEXT: CNDE_INT * T2.Y, T4.W, T0.W, T1.X, BS:VEC_120/SCL_212 +; R600-NEXT: ALU clause starting at 204: ; R600-NEXT: LSHL T0.Z, T0.Z, literal.x, -; R600-NEXT: MUL_IEEE T0.W, T0.Y, T7.X, +; R600-NEXT: MUL_IEEE T0.W, T1.Y, T8.X, ; R600-NEXT: SETGT * T1.W, literal.y, KC0[3].W, ; R600-NEXT: 23(3.222986e-44), -1026650416(-1.032789e+02) -; R600-NEXT: CNDE T4.X, PS, PV.W, 0.0, -; R600-NEXT: SETGT T0.Y, KC0[3].W, literal.x, +; R600-NEXT: CNDE T1.X, PS, PV.W, 0.0, +; R600-NEXT: SETGT T1.Y, KC0[3].W, literal.x, ; R600-NEXT: ADD_INT T0.Z, PV.Z, literal.y, -; R600-NEXT: CNDE_INT T0.W, T5.Y, T5.X, T1.Y, BS:VEC_102/SCL_221 -; R600-NEXT: CNDE * T1.W, T0.X, T3.X, literal.z, +; R600-NEXT: CNDE_INT T0.W, T3.Y, T2.Y, T4.X, BS:VEC_120/SCL_212 +; R600-NEXT: CNDE * T1.W, T2.X, T3.X, literal.z, ; R600-NEXT: 1118925336(8.872284e+01), 1065353216(1.000000e+00) ; R600-NEXT: 2139095040(INF), 0(0.000000e+00) -; R600-NEXT: MUL_IEEE T0.X, PV.W, PV.Z, +; R600-NEXT: MUL_IEEE T2.X, PV.W, PV.Z, ; R600-NEXT: SETGT T2.Y, literal.x, KC0[3].Y, ; R600-NEXT: CNDE T1.Z, PV.Y, PV.X, literal.y, -; R600-NEXT: CNDE T0.W, T2.X, T1.X, 0.0, +; R600-NEXT: CNDE T0.W, T0.X, T0.Y, 0.0, ; R600-NEXT: SETGT * T2.W, KC0[3].Z, literal.z, ; R600-NEXT: -1026650416(-1.032789e+02), 2139095040(INF) ; R600-NEXT: 1118925336(8.872284e+01), 0(0.000000e+00) @@ -2273,8 +2285,8 @@ define amdgpu_kernel void @s_exp_v4f32(ptr addrspace(1) %out, <4 x float> %in) { ; CM-LABEL: s_exp_v4f32: ; CM: ; %bb.0: ; CM-NEXT: ALU 97, @6, KC0[CB0:0-32], KC1[] -; CM-NEXT: ALU 97, @104, KC0[CB0:0-32], KC1[] -; CM-NEXT: ALU 35, @202, KC0[CB0:0-32], KC1[] +; CM-NEXT: ALU 100, @104, KC0[CB0:0-32], KC1[] +; CM-NEXT: ALU 36, @205, KC0[CB0:0-32], KC1[] ; CM-NEXT: MEM_RAT_CACHELESS STORE_DWORD T0, T1.X ; CM-NEXT: CF_END ; CM-NEXT: PAD @@ -2293,220 +2305,224 @@ define amdgpu_kernel void @s_exp_v4f32(ptr addrspace(1) %out, <4 x float> %in) { ; CM-NEXT: 1069064192(1.442383e+00), 0(0.000000e+00) ; CM-NEXT: MULADD_IEEE T0.X, T0.W, literal.x, PV.W, ; CM-NEXT: ADD T0.Y, T0.Z, -PV.Z, -; CM-NEXT: MUL_IEEE T0.Z, T2.W, literal.y, BS:VEC_120/SCL_212 -; CM-NEXT: MUL_IEEE * T0.W, PV.Y, literal.x, +; CM-NEXT: MUL_IEEE T0.Z, PV.Y, literal.x, +; CM-NEXT: MUL_IEEE * T0.W, T2.W, literal.y, BS:VEC_120/SCL_212 ; CM-NEXT: 967029397(3.122284e-04), 1069064192(1.442383e+00) ; CM-NEXT: TRUNC T1.X, T1.Z, -; CM-NEXT: MULADD_IEEE T1.Y, T1.Y, literal.x, PV.W, -; CM-NEXT: RNDNE T1.Z, PV.Z, -; CM-NEXT: ADD * T0.W, PV.Y, PV.X, +; CM-NEXT: RNDNE T2.Y, PV.W, +; CM-NEXT: MULADD_IEEE T0.Z, T1.Y, literal.x, PV.Z, +; CM-NEXT: ADD * T1.W, PV.Y, PV.X, ; CM-NEXT: 1069064192(1.442383e+00), 0(0.000000e+00) -; CM-NEXT: EXP_IEEE T0.X, T0.W, -; CM-NEXT: EXP_IEEE T0.Y (MASKED), T0.W, -; CM-NEXT: EXP_IEEE T0.Z (MASKED), T0.W, -; CM-NEXT: EXP_IEEE * T0.W (MASKED), T0.W, -; CM-NEXT: TRUNC T2.X, T1.Z, -; CM-NEXT: MULADD_IEEE T0.Y, T2.W, literal.x, T1.Y, -; CM-NEXT: FLT_TO_INT T2.Z, T1.X, -; CM-NEXT: MUL_IEEE * T0.W, PV.X, literal.y, -; CM-NEXT: 967029397(3.122284e-04), 209715200(1.972152e-31) -; CM-NEXT: ADD T1.X, T0.Z, -T1.Z, -; CM-NEXT: MUL_IEEE T1.Y, PV.W, literal.x, -; CM-NEXT: MAX_INT T0.Z, PV.Z, literal.y, -; CM-NEXT: MIN_INT * T1.W, PV.Z, literal.z, -; CM-NEXT: 209715200(1.972152e-31), -330(nan) -; CM-NEXT: 381(5.338947e-43), 0(0.000000e+00) -; CM-NEXT: ADD_INT T3.X, PV.W, literal.x, -; CM-NEXT: ADD_INT T2.Y, PV.Z, literal.y, -; CM-NEXT: ADD_INT T0.Z, T2.Z, literal.z, -; CM-NEXT: SETGT_UINT * T1.W, T2.Z, literal.w, -; CM-NEXT: -254(nan), 204(2.858649e-43) -; CM-NEXT: 102(1.429324e-43), -229(nan) -; CM-NEXT: ADD_INT T4.X, T2.Z, literal.x, -; CM-NEXT: SETGT_UINT T3.Y, T2.Z, literal.y, -; CM-NEXT: CNDE_INT T0.Z, PV.W, PV.Y, PV.Z, -; CM-NEXT: SETGT_INT * T2.W, T2.Z, literal.x, -; CM-NEXT: -127(nan), 254(3.559298e-43) -; CM-NEXT: MUL_IEEE T5.X, T0.X, literal.x, -; CM-NEXT: CNDE_INT T2.Y, PV.W, PV.Z, T2.Z, -; CM-NEXT: CNDE_INT T0.Z, PV.Y, PV.X, T3.X, -; CM-NEXT: SETGT_INT * T3.W, T2.Z, literal.y, -; CM-NEXT: 2130706432(1.701412e+38), 127(1.779649e-43) -; CM-NEXT: AND_INT T3.X, KC0[3].Z, literal.x, -; CM-NEXT: CNDE_INT T2.Y, PV.W, PV.Y, PV.Z, -; CM-NEXT: MUL_IEEE T0.Z, PV.X, literal.y, -; CM-NEXT: CNDE_INT * T0.W, T1.W, T1.Y, T0.W, -; CM-NEXT: -4096(nan), 2130706432(1.701412e+38) -; CM-NEXT: CNDE_INT T0.X, T2.W, PV.W, T0.X, -; CM-NEXT: CNDE_INT T1.Y, T3.Y, T5.X, PV.Z, -; CM-NEXT: LSHL T0.Z, PV.Y, literal.x, -; CM-NEXT: MUL_IEEE * T0.W, PV.X, literal.y, -; CM-NEXT: 23(3.222986e-44), 1069064192(1.442383e+00) -; CM-NEXT: RNDNE T4.X, PV.W, -; CM-NEXT: ADD_INT T2.Y, PV.Z, literal.x, -; CM-NEXT: CNDE_INT T0.Z, T3.W, PV.X, PV.Y, -; CM-NEXT: ADD * T1.W, T1.X, T0.Y, -; CM-NEXT: 1065353216(1.000000e+00), 0(0.000000e+00) ; CM-NEXT: EXP_IEEE T0.X, T1.W, ; CM-NEXT: EXP_IEEE T0.Y (MASKED), T1.W, ; CM-NEXT: EXP_IEEE T0.Z (MASKED), T1.W, ; CM-NEXT: EXP_IEEE * T0.W (MASKED), T1.W, -; CM-NEXT: MUL_IEEE T1.X, T0.Z, T2.Y, -; CM-NEXT: TRUNC T0.Y, T4.X, -; CM-NEXT: FLT_TO_INT T0.Z, T2.X, BS:VEC_120/SCL_212 -; CM-NEXT: MUL_IEEE * T1.W, PV.X, literal.x, -; CM-NEXT: 209715200(1.972152e-31), 0(0.000000e+00) -; CM-NEXT: MUL_IEEE T2.X, PV.W, literal.x, +; CM-NEXT: MULADD_IEEE T2.X, T2.W, literal.x, T0.Z, +; CM-NEXT: ADD T0.Y, T0.W, -T2.Y, BS:VEC_120/SCL_212 +; CM-NEXT: FLT_TO_INT T0.Z, T1.X, +; CM-NEXT: MUL_IEEE * T0.W, PV.X, literal.y, +; CM-NEXT: 967029397(3.122284e-04), 209715200(1.972152e-31) +; CM-NEXT: MUL_IEEE T1.X, PV.W, literal.x, ; CM-NEXT: MUL_IEEE T1.Y, T0.X, literal.y, ; CM-NEXT: MAX_INT T1.Z, PV.Z, literal.z, -; CM-NEXT: MIN_INT * T2.W, PV.Z, literal.w, +; CM-NEXT: MIN_INT * T1.W, PV.Z, literal.w, ; CM-NEXT: 209715200(1.972152e-31), 2130706432(1.701412e+38) ; CM-NEXT: -330(nan), 381(5.338947e-43) -; CM-NEXT: ADD_INT T5.X, PV.W, literal.x, -; CM-NEXT: ADD_INT T2.Y, PV.Z, literal.y, +; CM-NEXT: ADD_INT T3.X, PV.W, literal.x, +; CM-NEXT: ADD_INT T3.Y, PV.Z, literal.y, ; CM-NEXT: ADD_INT T1.Z, T0.Z, literal.z, -; CM-NEXT: SETGT_UINT * T2.W, T0.Z, literal.w, +; CM-NEXT: SETGT_UINT * T1.W, T0.Z, literal.w, ; CM-NEXT: -254(nan), 204(2.858649e-43) ; CM-NEXT: 102(1.429324e-43), -229(nan) -; CM-NEXT: ADD_INT T6.X, T0.Z, literal.x, -; CM-NEXT: SETGT_UINT T3.Y, T0.Z, literal.y, +; CM-NEXT: ADD_INT T4.X, T0.Z, literal.x, +; CM-NEXT: SETGT_UINT T4.Y, T0.Z, literal.y, ; CM-NEXT: CNDE_INT T1.Z, PV.W, PV.Y, PV.Z, -; CM-NEXT: SETGT_INT * T3.W, T0.Z, literal.x, +; CM-NEXT: SETGT_INT * T2.W, T0.Z, literal.x, ; CM-NEXT: -127(nan), 254(3.559298e-43) -; CM-NEXT: CNDE_INT T7.X, PV.W, PV.Z, T0.Z, -; CM-NEXT: CNDE_INT T2.Y, PV.Y, PV.X, T5.X, -; CM-NEXT: SETGT_INT * T0.Z, T0.Z, literal.x, -; CM-NEXT: 127(1.779649e-43), 0(0.000000e+00) -; CM-NEXT: ALU clause starting at 104: -; CM-NEXT: ADD * T4.W, KC0[3].Z, -T3.X, -; CM-NEXT: MUL_IEEE T5.X, PV.W, literal.x, -; CM-NEXT: CNDE_INT T2.Y, T0.Z, T7.X, T2.Y, -; CM-NEXT: MUL_IEEE T1.Z, T1.Y, literal.y, -; CM-NEXT: CNDE_INT * T1.W, T2.W, T2.X, T1.W, BS:VEC_021/SCL_122 -; CM-NEXT: 967029397(3.122284e-04), 2130706432(1.701412e+38) -; CM-NEXT: CNDE_INT T0.X, T3.W, PV.W, T0.X, -; CM-NEXT: CNDE_INT T1.Y, T3.Y, T1.Y, PV.Z, -; CM-NEXT: LSHL T1.Z, PV.Y, literal.x, -; CM-NEXT: MULADD_IEEE * T1.W, T4.W, literal.y, PV.X, BS:VEC_120/SCL_212 -; CM-NEXT: 23(3.222986e-44), 1069064192(1.442383e+00) -; CM-NEXT: MULADD_IEEE T2.X, T3.X, literal.x, PV.W, -; CM-NEXT: ADD T2.Y, T0.W, -T4.X, -; CM-NEXT: ADD_INT T1.Z, PV.Z, literal.y, -; CM-NEXT: CNDE_INT * T0.W, T0.Z, PV.X, PV.Y, +; CM-NEXT: CNDE_INT T5.X, PV.W, PV.Z, T0.Z, +; CM-NEXT: CNDE_INT T3.Y, PV.Y, PV.X, T3.X, +; CM-NEXT: SETGT_INT T0.Z, T0.Z, literal.x, +; CM-NEXT: MUL_IEEE * T3.W, T1.Y, literal.y, +; CM-NEXT: 127(1.779649e-43), 2130706432(1.701412e+38) +; CM-NEXT: CNDE_INT T3.X, T4.Y, T1.Y, PV.W, +; CM-NEXT: AND_INT T1.Y, KC0[3].Z, literal.x, +; CM-NEXT: CNDE_INT T1.Z, PV.Z, PV.X, PV.Y, +; CM-NEXT: CNDE_INT * T0.W, T1.W, T1.X, T0.W, +; CM-NEXT: -4096(nan), 0(0.000000e+00) +; CM-NEXT: CNDE_INT T0.X, T2.W, PV.W, T0.X, +; CM-NEXT: LSHL T3.Y, PV.Z, literal.x, +; CM-NEXT: TRUNC T1.Z, T2.Y, +; CM-NEXT: ADD * T0.W, KC0[3].Z, -PV.Y, +; CM-NEXT: 23(3.222986e-44), 0(0.000000e+00) +; CM-NEXT: MUL_IEEE T1.X, PV.W, literal.x, +; CM-NEXT: FLT_TO_INT T2.Y, PV.Z, +; CM-NEXT: ADD_INT T1.Z, PV.Y, literal.y, +; CM-NEXT: CNDE_INT * T1.W, T0.Z, PV.X, T3.X, ; CM-NEXT: 967029397(3.122284e-04), 1065353216(1.000000e+00) -; CM-NEXT: AND_INT T0.X, KC0[4].X, literal.x, -; CM-NEXT: MUL_IEEE T1.Y, PV.W, PV.Z, -; CM-NEXT: SETGT T0.Z, literal.y, KC0[3].W, -; CM-NEXT: ADD * T0.W, PV.Y, PV.X, -; CM-NEXT: -4096(nan), -1026650416(-1.032789e+02) +; CM-NEXT: MUL_IEEE T0.X, PV.W, PV.Z, +; CM-NEXT: MIN_INT T3.Y, PV.Y, literal.x, +; CM-NEXT: MULADD_IEEE T0.Z, T0.W, literal.y, PV.X, +; CM-NEXT: ADD * T0.W, T0.Y, T2.X, +; CM-NEXT: 381(5.338947e-43), 1069064192(1.442383e+00) +; CM-NEXT: EXP_IEEE T0.X (MASKED), T0.W, +; CM-NEXT: EXP_IEEE T0.Y, T0.W, +; CM-NEXT: EXP_IEEE T0.Z (MASKED), T0.W, +; CM-NEXT: EXP_IEEE * T0.W (MASKED), T0.W, +; CM-NEXT: MULADD_IEEE T1.X, T1.Y, literal.x, T0.Z, +; CM-NEXT: MUL_IEEE T4.Y, PV.Y, literal.y, +; CM-NEXT: ADD_INT T0.Z, T3.Y, literal.z, BS:VEC_120/SCL_212 +; CM-NEXT: MAX_INT * T0.W, T2.Y, literal.w, BS:VEC_201 +; CM-NEXT: 967029397(3.122284e-04), 2130706432(1.701412e+38) +; CM-NEXT: -254(nan), -330(nan) +; CM-NEXT: ADD_INT T2.X, T2.Y, literal.x, +; CM-NEXT: ADD_INT T3.Y, PV.W, literal.y, +; CM-NEXT: ADD_INT T1.Z, T2.Y, literal.z, +; CM-NEXT: SETGT_UINT * T0.W, T2.Y, literal.w, +; CM-NEXT: -127(nan), 204(2.858649e-43) +; CM-NEXT: 102(1.429324e-43), -229(nan) +; CM-NEXT: SETGT_UINT T3.X, T2.Y, literal.x, +; CM-NEXT: CNDE_INT T3.Y, PV.W, PV.Y, PV.Z, +; CM-NEXT: SETGT_INT T1.Z, T2.Y, literal.y, +; CM-NEXT: MUL_IEEE * T1.W, T0.Y, literal.z, BS:VEC_120/SCL_212 +; CM-NEXT: 254(3.559298e-43), -127(nan) +; CM-NEXT: 209715200(1.972152e-31), 0(0.000000e+00) +; CM-NEXT: MUL_IEEE T4.X, PV.W, literal.x, +; CM-NEXT: CNDE_INT * T3.Y, PV.Z, PV.Y, T2.Y, +; CM-NEXT: 209715200(1.972152e-31), 0(0.000000e+00) +; CM-NEXT: ALU clause starting at 104: +; CM-NEXT: CNDE_INT T0.Z, T3.X, T2.X, T0.Z, +; CM-NEXT: SETGT_INT * T2.W, T2.Y, literal.x, +; CM-NEXT: 127(1.779649e-43), 0(0.000000e+00) +; CM-NEXT: MUL_IEEE T2.X, T1.Y, literal.x, +; CM-NEXT: CNDE_INT T1.Y, PV.W, T3.Y, PV.Z, +; CM-NEXT: CNDE_INT T0.Z, T0.W, T4.X, T1.W, +; CM-NEXT: MUL_IEEE * T0.W, T4.Y, literal.y, BS:VEC_201 +; CM-NEXT: 1069064192(1.442383e+00), 2130706432(1.701412e+38) +; CM-NEXT: AND_INT T4.X, KC0[4].X, literal.x, +; CM-NEXT: CNDE_INT T2.Y, T3.X, T4.Y, PV.W, +; CM-NEXT: CNDE_INT T0.Z, T1.Z, PV.Z, T0.Y, +; CM-NEXT: LSHL * T0.W, PV.Y, literal.y, +; CM-NEXT: -4096(nan), 23(3.222986e-44) +; CM-NEXT: ADD_INT T3.X, PV.W, literal.x, +; CM-NEXT: CNDE_INT T0.Y, T2.W, PV.Z, PV.Y, +; CM-NEXT: MUL_IEEE T0.Z, PV.X, literal.y, +; CM-NEXT: RNDNE * T0.W, T2.X, +; CM-NEXT: 1065353216(1.000000e+00), 1069064192(1.442383e+00) +; CM-NEXT: ADD T2.X, T2.X, -PV.W, +; CM-NEXT: RNDNE T1.Y, PV.Z, +; CM-NEXT: MUL_IEEE T1.Z, PV.Y, PV.X, +; CM-NEXT: SETGT * T1.W, literal.x, KC0[3].W, +; CM-NEXT: -1026650416(-1.032789e+02), 0(0.000000e+00) +; CM-NEXT: CNDE T3.X, PV.W, PV.Z, 0.0, +; CM-NEXT: TRUNC T0.Y, T0.W, +; CM-NEXT: TRUNC T1.Z, PV.Y, +; CM-NEXT: ADD * T0.W, PV.X, T1.X, ; CM-NEXT: EXP_IEEE T0.X (MASKED), T0.W, ; CM-NEXT: EXP_IEEE T0.Y (MASKED), T0.W, ; CM-NEXT: EXP_IEEE T0.Z (MASKED), T0.W, ; CM-NEXT: EXP_IEEE * T0.W, T0.W, -; CM-NEXT: CNDE T2.X, T0.Z, T1.Y, 0.0, -; CM-NEXT: ADD T1.Y, KC0[4].X, -T0.X, -; CM-NEXT: FLT_TO_INT T0.Z, T0.Y, -; CM-NEXT: MUL_IEEE * T1.W, PV.W, literal.x, -; CM-NEXT: 209715200(1.972152e-31), 0(0.000000e+00) -; CM-NEXT: MUL_IEEE T3.X, PV.W, literal.x, -; CM-NEXT: SETGT_UINT T0.Y, PV.Z, literal.y, -; CM-NEXT: MUL_IEEE T1.Z, PV.Y, literal.z, -; CM-NEXT: MUL_IEEE * T2.W, T0.X, literal.w, -; CM-NEXT: 209715200(1.972152e-31), -229(nan) -; CM-NEXT: 967029397(3.122284e-04), 1069064192(1.442383e+00) -; CM-NEXT: RNDNE T4.X, PV.W, -; CM-NEXT: MULADD_IEEE T1.Y, T1.Y, literal.x, PV.Z, -; CM-NEXT: CNDE_INT T1.Z, PV.Y, PV.X, T1.W, -; CM-NEXT: SETGT_INT * T1.W, T0.Z, literal.y, -; CM-NEXT: 1069064192(1.442383e+00), -127(nan) -; CM-NEXT: CNDE_INT T3.X, PV.W, PV.Z, T0.W, -; CM-NEXT: MULADD_IEEE T1.Y, T0.X, literal.x, PV.Y, -; CM-NEXT: ADD T1.Z, T2.W, -PV.X, -; CM-NEXT: MAX_INT * T2.W, T0.Z, literal.y, +; CM-NEXT: FLT_TO_INT T1.X, T1.Z, +; CM-NEXT: FLT_TO_INT T0.Y, T0.Y, +; CM-NEXT: MUL_IEEE T1.Z, PV.W, literal.x, +; CM-NEXT: ADD * T1.W, KC0[4].X, -T4.X, +; CM-NEXT: 2130706432(1.701412e+38), 0(0.000000e+00) +; CM-NEXT: MUL_IEEE T2.X, PV.W, literal.x, +; CM-NEXT: MUL_IEEE T2.Y, T0.W, literal.y, +; CM-NEXT: MUL_IEEE T2.Z, PV.Z, literal.z, +; CM-NEXT: SETGT_UINT * T2.W, PV.Y, literal.w, +; CM-NEXT: 967029397(3.122284e-04), 209715200(1.972152e-31) +; CM-NEXT: 2130706432(1.701412e+38), 254(3.559298e-43) +; CM-NEXT: CNDE_INT T5.X, PV.W, T1.Z, PV.Z, +; CM-NEXT: MUL_IEEE T3.Y, PV.Y, literal.x, +; CM-NEXT: MULADD_IEEE T1.Z, T1.W, literal.y, PV.X, +; CM-NEXT: MAX_INT * T1.W, T1.X, literal.z, +; CM-NEXT: 209715200(1.972152e-31), 1069064192(1.442383e+00) +; CM-NEXT: -330(nan), 0(0.000000e+00) +; CM-NEXT: ADD_INT T2.X, PV.W, literal.x, +; CM-NEXT: ADD_INT T4.Y, T1.X, literal.y, +; CM-NEXT: MULADD_IEEE T1.Z, T4.X, literal.z, PV.Z, BS:VEC_120/SCL_212 +; CM-NEXT: MAX_INT * T1.W, T0.Y, literal.w, +; CM-NEXT: 204(2.858649e-43), 102(1.429324e-43) ; CM-NEXT: 967029397(3.122284e-04), -330(nan) -; CM-NEXT: ADD_INT T0.X, PV.W, literal.x, -; CM-NEXT: ADD_INT T2.Y, T0.Z, literal.y, -; CM-NEXT: TRUNC T2.Z, T4.X, -; CM-NEXT: ADD * T2.W, PV.Z, PV.Y, +; CM-NEXT: ADD T4.X, T0.Z, -T1.Y, +; CM-NEXT: ADD_INT T1.Y, PV.W, literal.x, +; CM-NEXT: ADD_INT T0.Z, T0.Y, literal.y, +; CM-NEXT: SETGT_UINT * T1.W, T0.Y, literal.z, ; CM-NEXT: 204(2.858649e-43), 102(1.429324e-43) -; CM-NEXT: EXP_IEEE T1.X (MASKED), T2.W, -; CM-NEXT: EXP_IEEE T1.Y, T2.W, -; CM-NEXT: EXP_IEEE T1.Z (MASKED), T2.W, -; CM-NEXT: EXP_IEEE * T1.W (MASKED), T2.W, -; CM-NEXT: MUL_IEEE T4.X, T0.W, literal.x, -; CM-NEXT: FLT_TO_INT T3.Y, T2.Z, -; CM-NEXT: MUL_IEEE T1.Z, PV.Y, literal.y, -; CM-NEXT: CNDE_INT * T0.W, T0.Y, T0.X, T2.Y, +; CM-NEXT: -229(nan), 0(0.000000e+00) +; CM-NEXT: SETGT_UINT T6.X, T1.X, literal.x, +; CM-NEXT: CNDE_INT T1.Y, PV.W, PV.Y, PV.Z, +; CM-NEXT: SETGT_INT T0.Z, T0.Y, literal.y, +; CM-NEXT: ADD * T3.W, PV.X, T1.Z, +; CM-NEXT: -229(nan), -127(nan) +; CM-NEXT: EXP_IEEE T1.X (MASKED), T3.W, +; CM-NEXT: EXP_IEEE T1.Y (MASKED), T3.W, +; CM-NEXT: EXP_IEEE T1.Z, T3.W, +; CM-NEXT: EXP_IEEE * T1.W (MASKED), T3.W, +; CM-NEXT: CNDE_INT T4.X, T0.Z, T1.Y, T0.Y, +; CM-NEXT: CNDE_INT T1.Y, T6.X, T2.X, T4.Y, BS:VEC_120/SCL_212 +; CM-NEXT: SETGT_INT T2.Z, T1.X, literal.x, +; CM-NEXT: MUL_IEEE * T3.W, PV.Z, literal.y, +; CM-NEXT: -127(nan), 209715200(1.972152e-31) +; CM-NEXT: MUL_IEEE T2.X, T1.Z, literal.x, +; CM-NEXT: MUL_IEEE T4.Y, PV.W, literal.y, +; CM-NEXT: CNDE_INT T3.Z, PV.Z, PV.Y, T1.X, +; CM-NEXT: MIN_INT * T4.W, T1.X, literal.z, ; CM-NEXT: 2130706432(1.701412e+38), 209715200(1.972152e-31) -; CM-NEXT: CNDE_INT T0.X, T1.W, PV.W, T0.Z, -; CM-NEXT: MUL_IEEE T0.Y, PV.Z, literal.x, -; CM-NEXT: MAX_INT T2.Z, PV.Y, literal.y, -; CM-NEXT: MIN_INT * T0.W, PV.Y, literal.z, -; CM-NEXT: 209715200(1.972152e-31), -330(nan) ; CM-NEXT: 381(5.338947e-43), 0(0.000000e+00) -; CM-NEXT: ADD_INT T5.X, PV.W, literal.x, -; CM-NEXT: ADD_INT T2.Y, PV.Z, literal.y, -; CM-NEXT: ADD_INT T2.Z, T3.Y, literal.z, -; CM-NEXT: SETGT_UINT * T0.W, T3.Y, literal.w, -; CM-NEXT: -254(nan), 204(2.858649e-43) -; CM-NEXT: 102(1.429324e-43), -229(nan) -; CM-NEXT: ADD_INT T6.X, T3.Y, literal.x, -; CM-NEXT: SETGT_UINT T4.Y, T3.Y, literal.y, -; CM-NEXT: CNDE_INT T2.Z, PV.W, PV.Y, PV.Z, -; CM-NEXT: SETGT_INT * T1.W, T3.Y, literal.x, +; CM-NEXT: MIN_INT T7.X, T0.Y, literal.x, +; CM-NEXT: ADD_INT T1.Y, PV.W, literal.y, +; CM-NEXT: ADD_INT T4.Z, T1.X, literal.z, +; CM-NEXT: SETGT_UINT * T4.W, T1.X, literal.w, +; CM-NEXT: 381(5.338947e-43), -254(nan) ; CM-NEXT: -127(nan), 254(3.559298e-43) -; CM-NEXT: MUL_IEEE T7.X, T1.Y, literal.x, -; CM-NEXT: CNDE_INT T2.Y, PV.W, PV.Z, T3.Y, -; CM-NEXT: CNDE_INT T2.Z, PV.Y, PV.X, T5.X, -; CM-NEXT: MIN_INT * T2.W, T0.Z, literal.y, -; CM-NEXT: 2130706432(1.701412e+38), 381(5.338947e-43) -; CM-NEXT: SETGT_INT T5.X, T3.Y, literal.x, -; CM-NEXT: ADD_INT T3.Y, PV.W, literal.y, -; CM-NEXT: ADD_INT T3.Z, T0.Z, literal.z, -; CM-NEXT: SETGT_UINT * T2.W, T0.Z, literal.w, +; CM-NEXT: CNDE_INT T8.X, PV.W, PV.Z, PV.Y, +; CM-NEXT: SETGT_INT T1.Y, T1.X, literal.x, +; CM-NEXT: ADD_INT T4.Z, PV.X, literal.y, +; CM-NEXT: ADD_INT * T5.W, T0.Y, literal.z, ; CM-NEXT: 127(1.779649e-43), -254(nan) -; CM-NEXT: -127(nan), 254(3.559298e-43) -; CM-NEXT: CNDE_INT T6.X, PV.W, PV.Z, PV.Y, -; CM-NEXT: CNDE_INT T2.Y, PV.X, T2.Y, T2.Z, -; CM-NEXT: MUL_IEEE T2.Z, T7.X, literal.x, -; CM-NEXT: CNDE_INT * T0.W, T0.W, T0.Y, T1.Z, BS:VEC_021/SCL_122 +; CM-NEXT: -127(nan), 0(0.000000e+00) +; CM-NEXT: CNDE_INT T1.X, T2.W, PV.W, PV.Z, +; CM-NEXT: CNDE_INT T5.Y, PV.Y, T3.Z, PV.X, +; CM-NEXT: CNDE_INT T3.Z, T6.X, T4.Y, T3.W, +; CM-NEXT: MUL_IEEE * T2.W, T2.X, literal.x, BS:VEC_120/SCL_212 ; CM-NEXT: 2130706432(1.701412e+38), 0(0.000000e+00) -; CM-NEXT: SETGT_INT T8.X, T0.Z, literal.x, -; CM-NEXT: CNDE_INT T0.Y, T1.W, PV.W, T1.Y, -; CM-NEXT: CNDE_INT T0.Z, T4.Y, T7.X, PV.Z, -; CM-NEXT: LSHL * T0.W, PV.Y, literal.y, -; CM-NEXT: 127(1.779649e-43), 23(3.222986e-44) -; CM-NEXT: ALU clause starting at 202: -; CM-NEXT: ADD_INT T7.X, T0.W, literal.x, -; CM-NEXT: CNDE_INT * T0.Y, T5.X, T0.Y, T0.Z, +; CM-NEXT: SETGT_INT T6.X, T0.Y, literal.x, +; CM-NEXT: CNDE_INT T0.Y, T4.W, T2.X, PV.W, +; CM-NEXT: CNDE_INT * T1.Z, T2.Z, PV.Z, T1.Z, +; CM-NEXT: 127(1.779649e-43), 0(0.000000e+00) +; CM-NEXT: ALU clause starting at 205: +; CM-NEXT: LSHL * T2.W, T5.Y, literal.x, +; CM-NEXT: 23(3.222986e-44), 0(0.000000e+00) +; CM-NEXT: ADD_INT T2.X, PV.W, literal.x, +; CM-NEXT: CNDE_INT T0.Y, T1.Y, T1.Z, T0.Y, +; CM-NEXT: CNDE_INT * T1.Z, T6.X, T4.X, T1.X, ; CM-NEXT: 1065353216(1.000000e+00), 0(0.000000e+00) -; CM-NEXT: CNDE_INT * T0.Z, T8.X, T0.X, T6.X, -; CM-NEXT: MUL_IEEE * T0.W, T4.X, literal.x, -; CM-NEXT: 2130706432(1.701412e+38), 0(0.000000e+00) -; CM-NEXT: CNDE_INT T0.X, T2.W, T4.X, PV.W, -; CM-NEXT: LSHL T1.Y, T0.Z, literal.x, -; CM-NEXT: MUL_IEEE T0.Z, T0.Y, T7.X, BS:VEC_021/SCL_122 +; CM-NEXT: CNDE_INT * T1.W, T1.W, T3.Y, T2.Y, +; CM-NEXT: CNDE_INT T1.X, T0.Z, PV.W, T0.W, +; CM-NEXT: LSHL T1.Y, T1.Z, literal.x, BS:VEC_120/SCL_212 +; CM-NEXT: MUL_IEEE T0.Z, T0.Y, T2.X, ; CM-NEXT: SETGT * T0.W, literal.y, KC0[4].X, ; CM-NEXT: 23(3.222986e-44), -1026650416(-1.032789e+02) -; CM-NEXT: CNDE T4.X, PV.W, PV.Z, 0.0, +; CM-NEXT: CNDE T2.X, PV.W, PV.Z, 0.0, ; CM-NEXT: SETGT T0.Y, KC0[4].X, literal.x, ; CM-NEXT: ADD_INT T0.Z, PV.Y, literal.y, -; CM-NEXT: CNDE_INT * T0.W, T8.X, T3.X, PV.X, +; CM-NEXT: CNDE_INT * T0.W, T6.X, PV.X, T5.X, ; CM-NEXT: 1118925336(8.872284e+01), 1065353216(1.000000e+00) -; CM-NEXT: SETGT T0.X, KC0[3].W, literal.x, +; CM-NEXT: SETGT T1.X, KC0[3].W, literal.x, ; CM-NEXT: MUL_IEEE T1.Y, PV.W, PV.Z, ; CM-NEXT: SETGT T0.Z, literal.y, KC0[3].Z, ; CM-NEXT: CNDE * T0.W, PV.Y, PV.X, literal.z, ; CM-NEXT: 1118925336(8.872284e+01), -1026650416(-1.032789e+02) ; CM-NEXT: 2139095040(INF), 0(0.000000e+00) -; CM-NEXT: SETGT T3.X, literal.x, KC0[3].Y, +; CM-NEXT: SETGT T2.X, literal.x, KC0[3].Y, ; CM-NEXT: CNDE T0.Y, PV.Z, PV.Y, 0.0, -; CM-NEXT: CNDE T0.Z, PV.X, T2.X, literal.y, +; CM-NEXT: CNDE T0.Z, PV.X, T3.X, literal.y, ; CM-NEXT: SETGT * T1.W, KC0[3].Z, literal.z, ; CM-NEXT: -1026650416(-1.032789e+02), 2139095040(INF) ; CM-NEXT: 1118925336(8.872284e+01), 0(0.000000e+00) ; CM-NEXT: CNDE T0.Y, PV.W, PV.Y, literal.x, -; CM-NEXT: CNDE T1.Z, PV.X, T1.X, 0.0, +; CM-NEXT: CNDE T1.Z, PV.X, T0.X, 0.0, ; CM-NEXT: SETGT * T1.W, KC0[3].Y, literal.y, ; CM-NEXT: 2139095040(INF), 1118925336(8.872284e+01) ; CM-NEXT: CNDE * T0.X, PV.W, PV.Z, literal.x, diff --git a/llvm/test/CodeGen/AMDGPU/llvm.exp10.ll b/llvm/test/CodeGen/AMDGPU/llvm.exp10.ll index a16294958748..544c1de6c7bb 100644 --- a/llvm/test/CodeGen/AMDGPU/llvm.exp10.ll +++ b/llvm/test/CodeGen/AMDGPU/llvm.exp10.ll @@ -230,23 +230,23 @@ define amdgpu_kernel void @s_exp10_f32(ptr addrspace(1) %out, float %in) { ; R600-NEXT: MUL_IEEE * T2.W, PS, literal.z, ; R600-NEXT: -127(nan), 254(3.559298e-43) ; R600-NEXT: 209715200(1.972152e-31), 0(0.000000e+00) -; R600-NEXT: MUL_IEEE T3.X, PS, literal.x, -; R600-NEXT: MUL_IEEE T0.Y, T1.X, literal.y, +; R600-NEXT: MUL_IEEE T3.X, T1.X, literal.x, +; R600-NEXT: MUL_IEEE T0.Y, PS, literal.y, ; R600-NEXT: CNDE_INT T1.Z, PV.W, PV.Z, T0.Z, ; R600-NEXT: CNDE_INT T3.W, PV.Y, PV.X, T0.X, ; R600-NEXT: SETGT_INT * T4.W, T0.Z, literal.z, -; R600-NEXT: 209715200(1.972152e-31), 2130706432(1.701412e+38) +; R600-NEXT: 2130706432(1.701412e+38), 209715200(1.972152e-31) ; R600-NEXT: 127(1.779649e-43), 0(0.000000e+00) ; R600-NEXT: CNDE_INT T0.Z, PS, PV.Z, PV.W, -; R600-NEXT: MUL_IEEE T3.W, PV.Y, literal.x, -; R600-NEXT: CNDE_INT * T0.W, T0.W, PV.X, T2.W, +; R600-NEXT: CNDE_INT T0.W, T0.W, PV.Y, T2.W, +; R600-NEXT: MUL_IEEE * T2.W, PV.X, literal.x, ; R600-NEXT: 2130706432(1.701412e+38), 0(0.000000e+00) -; R600-NEXT: CNDE_INT T1.Z, T1.W, PS, T1.X, -; R600-NEXT: CNDE_INT T0.W, T1.Y, T0.Y, PV.W, +; R600-NEXT: CNDE_INT T1.Z, T1.Y, T3.X, PS, +; R600-NEXT: CNDE_INT T0.W, T1.W, PV.W, T1.X, ; R600-NEXT: LSHL * T1.W, PV.Z, literal.x, ; R600-NEXT: 23(3.222986e-44), 0(0.000000e+00) ; R600-NEXT: ADD_INT T1.W, PS, literal.x, -; R600-NEXT: CNDE_INT * T0.W, T4.W, PV.Z, PV.W, +; R600-NEXT: CNDE_INT * T0.W, T4.W, PV.W, PV.Z, ; R600-NEXT: 1065353216(1.000000e+00), 0(0.000000e+00) ; R600-NEXT: MUL_IEEE T0.W, PS, PV.W, ; R600-NEXT: SETGT * T1.W, literal.x, KC0[2].Z, @@ -260,63 +260,65 @@ define amdgpu_kernel void @s_exp10_f32(ptr addrspace(1) %out, float %in) { ; ; CM-LABEL: s_exp10_f32: ; CM: ; %bb.0: -; CM-NEXT: ALU 62, @4, KC0[CB0:0-32], KC1[] +; CM-NEXT: ALU 64, @4, KC0[CB0:0-32], KC1[] ; CM-NEXT: MEM_RAT_CACHELESS STORE_DWORD T0.X, T1.X ; CM-NEXT: CF_END ; CM-NEXT: PAD ; CM-NEXT: ALU clause starting at 4: ; CM-NEXT: AND_INT * T0.W, KC0[2].Z, literal.x, ; CM-NEXT: -4096(nan), 0(0.000000e+00) -; CM-NEXT: ADD * T1.W, KC0[2].Z, -PV.W, ; CM-NEXT: MUL_IEEE T0.Z, PV.W, literal.x, -; CM-NEXT: MUL_IEEE * T2.W, T0.W, literal.y, -; CM-NEXT: 975668412(6.390323e-04), 1079283712(3.321289e+00) -; CM-NEXT: RNDNE T1.Z, PV.W, +; CM-NEXT: ADD * T1.W, KC0[2].Z, -PV.W, +; CM-NEXT: 1079283712(3.321289e+00), 0(0.000000e+00) +; CM-NEXT: MUL_IEEE T1.Z, PV.W, literal.x, +; CM-NEXT: RNDNE * T2.W, PV.Z, +; CM-NEXT: 975668412(6.390323e-04), 0(0.000000e+00) +; CM-NEXT: TRUNC T2.Z, PV.W, ; CM-NEXT: MULADD_IEEE * T1.W, T1.W, literal.x, PV.Z, ; CM-NEXT: 1079283712(3.321289e+00), 0(0.000000e+00) -; CM-NEXT: MULADD_IEEE T0.Z, T0.W, literal.x, PV.W, -; CM-NEXT: ADD * T0.W, T2.W, -PV.Z, BS:VEC_120/SCL_212 +; CM-NEXT: MULADD_IEEE T0.Y, T0.W, literal.x, PV.W, +; CM-NEXT: ADD T0.Z, T0.Z, -T2.W, +; CM-NEXT: FLT_TO_INT * T0.W, PV.Z, ; CM-NEXT: 975668412(6.390323e-04), 0(0.000000e+00) -; CM-NEXT: TRUNC T1.Z, T1.Z, -; CM-NEXT: ADD * T0.W, PV.W, PV.Z, -; CM-NEXT: EXP_IEEE T0.X, T0.W, -; CM-NEXT: EXP_IEEE T0.Y (MASKED), T0.W, -; CM-NEXT: EXP_IEEE T0.Z (MASKED), T0.W, -; CM-NEXT: EXP_IEEE * T0.W (MASKED), T0.W, -; CM-NEXT: FLT_TO_INT T0.Z, T1.Z, -; CM-NEXT: MUL_IEEE * T0.W, PV.X, literal.x, -; CM-NEXT: 209715200(1.972152e-31), 0(0.000000e+00) -; CM-NEXT: MUL_IEEE T0.Y, PV.W, literal.x, -; CM-NEXT: MAX_INT T1.Z, PV.Z, literal.y, -; CM-NEXT: MIN_INT * T1.W, PV.Z, literal.z, -; CM-NEXT: 209715200(1.972152e-31), -330(nan) +; CM-NEXT: MIN_INT T1.Z, PV.W, literal.x, +; CM-NEXT: ADD * T1.W, PV.Z, PV.Y, ; CM-NEXT: 381(5.338947e-43), 0(0.000000e+00) -; CM-NEXT: ADD_INT T1.X, PV.W, literal.x, -; CM-NEXT: ADD_INT T1.Y, PV.Z, literal.y, -; CM-NEXT: ADD_INT T1.Z, T0.Z, literal.z, -; CM-NEXT: SETGT_UINT * T1.W, T0.Z, literal.w, -; CM-NEXT: -254(nan), 204(2.858649e-43) +; CM-NEXT: EXP_IEEE T0.X, T1.W, +; CM-NEXT: EXP_IEEE T0.Y (MASKED), T1.W, +; CM-NEXT: EXP_IEEE T0.Z (MASKED), T1.W, +; CM-NEXT: EXP_IEEE * T0.W (MASKED), T1.W, +; CM-NEXT: MUL_IEEE T0.Y, PV.X, literal.x, +; CM-NEXT: ADD_INT T0.Z, T1.Z, literal.y, +; CM-NEXT: MAX_INT * T1.W, T0.W, literal.z, +; CM-NEXT: 2130706432(1.701412e+38), -254(nan) +; CM-NEXT: -330(nan), 0(0.000000e+00) +; CM-NEXT: ADD_INT T1.X, T0.W, literal.x, +; CM-NEXT: ADD_INT T1.Y, PV.W, literal.y, +; CM-NEXT: ADD_INT T1.Z, T0.W, literal.z, +; CM-NEXT: SETGT_UINT * T1.W, T0.W, literal.w, +; CM-NEXT: -127(nan), 204(2.858649e-43) ; CM-NEXT: 102(1.429324e-43), -229(nan) -; CM-NEXT: ADD_INT T2.X, T0.Z, literal.x, -; CM-NEXT: SETGT_UINT T2.Y, T0.Z, literal.y, -; CM-NEXT: CNDE_INT T1.Z, PV.W, PV.Y, PV.Z, -; CM-NEXT: SETGT_INT * T2.W, T0.Z, literal.x, -; CM-NEXT: -127(nan), 254(3.559298e-43) -; CM-NEXT: MUL_IEEE T3.X, T0.X, literal.x, -; CM-NEXT: CNDE_INT T1.Y, PV.W, PV.Z, T0.Z, -; CM-NEXT: CNDE_INT T1.Z, PV.Y, PV.X, T1.X, -; CM-NEXT: SETGT_INT * T3.W, T0.Z, literal.y, -; CM-NEXT: 2130706432(1.701412e+38), 127(1.779649e-43) +; CM-NEXT: SETGT_UINT T2.X, T0.W, literal.x, ; CM-NEXT: CNDE_INT T1.Y, PV.W, PV.Y, PV.Z, -; CM-NEXT: MUL_IEEE T0.Z, PV.X, literal.x, -; CM-NEXT: CNDE_INT * T0.W, T1.W, T0.Y, T0.W, +; CM-NEXT: SETGT_INT T1.Z, T0.W, literal.y, +; CM-NEXT: MUL_IEEE * T2.W, T0.X, literal.z, +; CM-NEXT: 254(3.559298e-43), -127(nan) +; CM-NEXT: 209715200(1.972152e-31), 0(0.000000e+00) +; CM-NEXT: MUL_IEEE T3.X, PV.W, literal.x, +; CM-NEXT: CNDE_INT T1.Y, PV.Z, PV.Y, T0.W, +; CM-NEXT: CNDE_INT T0.Z, PV.X, T1.X, T0.Z, +; CM-NEXT: SETGT_INT * T0.W, T0.W, literal.y, +; CM-NEXT: 209715200(1.972152e-31), 127(1.779649e-43) +; CM-NEXT: CNDE_INT T1.Y, PV.W, PV.Y, PV.Z, +; CM-NEXT: CNDE_INT T0.Z, T1.W, PV.X, T2.W, +; CM-NEXT: MUL_IEEE * T1.W, T0.Y, literal.x, ; CM-NEXT: 2130706432(1.701412e+38), 0(0.000000e+00) -; CM-NEXT: CNDE_INT T0.Y, T2.W, PV.W, T0.X, -; CM-NEXT: CNDE_INT T0.Z, T2.Y, T3.X, PV.Z, -; CM-NEXT: LSHL * T0.W, PV.Y, literal.x, +; CM-NEXT: CNDE_INT T0.Y, T2.X, T0.Y, PV.W, +; CM-NEXT: CNDE_INT T0.Z, T1.Z, PV.Z, T0.X, +; CM-NEXT: LSHL * T1.W, PV.Y, literal.x, ; CM-NEXT: 23(3.222986e-44), 0(0.000000e+00) ; CM-NEXT: ADD_INT T1.Z, PV.W, literal.x, -; CM-NEXT: CNDE_INT * T0.W, T3.W, PV.Y, PV.Z, +; CM-NEXT: CNDE_INT * T0.W, T0.W, PV.Z, PV.Y, ; CM-NEXT: 1065353216(1.000000e+00), 0(0.000000e+00) ; CM-NEXT: MUL_IEEE T0.Z, PV.W, PV.Z, ; CM-NEXT: SETGT * T0.W, literal.x, KC0[2].Z, @@ -610,105 +612,105 @@ define amdgpu_kernel void @s_exp10_v2f32(ptr addrspace(1) %out, <2 x float> %in) ; R600-NEXT: AND_INT * T0.W, KC0[3].X, literal.x, ; R600-NEXT: -4096(nan), 0(0.000000e+00) ; R600-NEXT: ADD * T1.W, KC0[3].X, -PV.W, -; R600-NEXT: MUL_IEEE T2.W, PV.W, literal.x, -; R600-NEXT: MUL_IEEE * T3.W, T0.W, literal.y, -; R600-NEXT: 975668412(6.390323e-04), 1079283712(3.321289e+00) -; R600-NEXT: RNDNE T0.Z, PS, +; R600-NEXT: AND_INT T0.Z, KC0[2].W, literal.x, +; R600-NEXT: MUL_IEEE T2.W, PV.W, literal.y, +; R600-NEXT: MUL_IEEE * T3.W, T0.W, literal.z, +; R600-NEXT: -4096(nan), 975668412(6.390323e-04) +; R600-NEXT: 1079283712(3.321289e+00), 0(0.000000e+00) +; R600-NEXT: RNDNE T1.Z, PS, ; R600-NEXT: MULADD_IEEE T1.W, T1.W, literal.x, PV.W, -; R600-NEXT: AND_INT * T2.W, KC0[2].W, literal.y, -; R600-NEXT: 1079283712(3.321289e+00), -4096(nan) -; R600-NEXT: ADD T1.Z, KC0[2].W, -PS, +; R600-NEXT: ADD * T2.W, KC0[2].W, -PV.Z, +; R600-NEXT: 1079283712(3.321289e+00), 0(0.000000e+00) +; R600-NEXT: MUL_IEEE T0.Y, PS, literal.x, +; R600-NEXT: MUL_IEEE T2.Z, T0.Z, literal.y, ; R600-NEXT: MULADD_IEEE T0.W, T0.W, literal.x, PV.W, ; R600-NEXT: ADD * T1.W, T3.W, -PV.Z, -; R600-NEXT: 975668412(6.390323e-04), 0(0.000000e+00) -; R600-NEXT: ADD T2.Z, PS, PV.W, -; R600-NEXT: MUL_IEEE T0.W, PV.Z, literal.x, -; R600-NEXT: MUL_IEEE * T1.W, T2.W, literal.y, ; R600-NEXT: 975668412(6.390323e-04), 1079283712(3.321289e+00) -; R600-NEXT: RNDNE T0.Y, PS, -; R600-NEXT: MULADD_IEEE T1.Z, T1.Z, literal.x, PV.W, -; R600-NEXT: TRUNC T0.W, T0.Z, BS:VEC_120/SCL_212 -; R600-NEXT: EXP_IEEE * T0.X, PV.Z, +; R600-NEXT: ADD T3.Z, PS, PV.W, +; R600-NEXT: RNDNE T0.W, PV.Z, +; R600-NEXT: MULADD_IEEE * T1.W, T2.W, literal.x, PV.Y, BS:VEC_021/SCL_122 ; R600-NEXT: 1079283712(3.321289e+00), 0(0.000000e+00) -; R600-NEXT: FLT_TO_INT T1.Y, PV.W, -; R600-NEXT: MUL_IEEE T0.Z, PS, literal.x, -; R600-NEXT: MULADD_IEEE T0.W, T2.W, literal.y, PV.Z, -; R600-NEXT: ADD * T1.W, T1.W, -PV.Y, -; R600-NEXT: 209715200(1.972152e-31), 975668412(6.390323e-04) -; R600-NEXT: ADD T1.Z, PS, PV.W, -; R600-NEXT: MUL_IEEE T0.W, PV.Z, literal.x, -; R600-NEXT: SETGT_UINT * T1.W, PV.Y, literal.y, -; R600-NEXT: 209715200(1.972152e-31), -229(nan) -; R600-NEXT: CNDE_INT T0.Z, PS, PV.W, T0.Z, -; R600-NEXT: SETGT_INT T0.W, T1.Y, literal.x, -; R600-NEXT: EXP_IEEE * T1.X, PV.Z, -; R600-NEXT: -127(nan), 0(0.000000e+00) -; R600-NEXT: CNDE_INT T0.Z, PV.W, PV.Z, T0.X, -; R600-NEXT: MAX_INT T2.W, T1.Y, literal.x, -; R600-NEXT: MUL_IEEE * T3.W, PS, literal.y, -; R600-NEXT: -330(nan), 209715200(1.972152e-31) -; R600-NEXT: MUL_IEEE T2.X, PS, literal.x, -; R600-NEXT: ADD_INT T2.Y, PV.W, literal.y, -; R600-NEXT: ADD_INT T1.Z, T1.Y, literal.z, -; R600-NEXT: MIN_INT T2.W, T1.Y, literal.w, -; R600-NEXT: TRUNC * T4.W, T0.Y, -; R600-NEXT: 209715200(1.972152e-31), 204(2.858649e-43) -; R600-NEXT: 102(1.429324e-43), 381(5.338947e-43) -; R600-NEXT: FLT_TO_INT T3.X, PS, -; R600-NEXT: ADD_INT T0.Y, PV.W, literal.x, -; R600-NEXT: ADD_INT T2.Z, T1.Y, literal.y, -; R600-NEXT: SETGT_UINT T2.W, T1.Y, literal.z, -; R600-NEXT: CNDE_INT * T1.W, T1.W, PV.Y, PV.Z, -; R600-NEXT: -254(nan), -127(nan) -; R600-NEXT: 254(3.559298e-43), 0(0.000000e+00) -; R600-NEXT: MUL_IEEE T4.X, T1.X, literal.x, -; R600-NEXT: MUL_IEEE T2.Y, T0.X, literal.x, BS:VEC_120/SCL_212 -; R600-NEXT: CNDE_INT T1.Z, T0.W, PS, T1.Y, -; R600-NEXT: CNDE_INT T0.W, PV.W, PV.Z, PV.Y, -; R600-NEXT: MAX_INT * T1.W, PV.X, literal.y, +; R600-NEXT: TRUNC T0.Y, T1.Z, +; R600-NEXT: MULADD_IEEE T0.Z, T0.Z, literal.x, PS, BS:VEC_120/SCL_212 +; R600-NEXT: ADD T1.W, T2.Z, -PV.W, BS:VEC_201 +; R600-NEXT: EXP_IEEE * T0.X, PV.Z, +; R600-NEXT: 975668412(6.390323e-04), 0(0.000000e+00) +; R600-NEXT: ADD T0.Z, PV.W, PV.Z, +; R600-NEXT: FLT_TO_INT T1.W, PV.Y, +; R600-NEXT: MUL_IEEE * T2.W, PS, literal.x, +; R600-NEXT: 2130706432(1.701412e+38), 0(0.000000e+00) +; R600-NEXT: MUL_IEEE T1.Z, PS, literal.x, +; R600-NEXT: SETGT_UINT T3.W, PV.W, literal.y, +; R600-NEXT: EXP_IEEE * T0.Y, PV.Z, +; R600-NEXT: 2130706432(1.701412e+38), 254(3.559298e-43) +; R600-NEXT: CNDE_INT T1.X, PV.W, T2.W, PV.Z, +; R600-NEXT: MUL_IEEE T1.Y, PS, literal.x, +; R600-NEXT: MAX_INT T0.Z, T1.W, literal.y, +; R600-NEXT: MIN_INT T2.W, T1.W, literal.z, +; R600-NEXT: TRUNC * T0.W, T0.W, ; R600-NEXT: 2130706432(1.701412e+38), -330(nan) -; R600-NEXT: SETGT_INT T0.X, T1.Y, literal.x, -; R600-NEXT: ADD_INT T0.Y, PS, literal.y, -; R600-NEXT: ADD_INT T2.Z, T3.X, literal.z, -; R600-NEXT: SETGT_UINT * T1.W, T3.X, literal.w, +; R600-NEXT: 381(5.338947e-43), 0(0.000000e+00) +; R600-NEXT: FLT_TO_INT T2.X, PS, +; R600-NEXT: ADD_INT T2.Y, PV.W, literal.x, +; R600-NEXT: ADD_INT T0.Z, PV.Z, literal.y, +; R600-NEXT: ADD_INT T0.W, T1.W, literal.z, +; R600-NEXT: SETGT_UINT * T2.W, T1.W, literal.w, +; R600-NEXT: -254(nan), 204(2.858649e-43) +; R600-NEXT: 102(1.429324e-43), -229(nan) +; R600-NEXT: ADD_INT T3.X, T1.W, literal.x, +; R600-NEXT: CNDE_INT T3.Y, PS, PV.Z, PV.W, +; R600-NEXT: SETGT_INT T0.Z, T1.W, literal.x, +; R600-NEXT: MUL_IEEE T0.W, T0.X, literal.y, +; R600-NEXT: MUL_IEEE * T4.W, T0.Y, literal.y, +; R600-NEXT: -127(nan), 209715200(1.972152e-31) +; R600-NEXT: MUL_IEEE T4.X, PS, literal.x, +; R600-NEXT: MUL_IEEE T4.Y, PV.W, literal.x, +; R600-NEXT: CNDE_INT T1.Z, PV.Z, PV.Y, T1.W, +; R600-NEXT: CNDE_INT T3.W, T3.W, PV.X, T2.Y, +; R600-NEXT: MAX_INT * T5.W, T2.X, literal.y, +; R600-NEXT: 209715200(1.972152e-31), -330(nan) +; R600-NEXT: SETGT_INT T3.X, T1.W, literal.x, +; R600-NEXT: ADD_INT T2.Y, PS, literal.y, +; R600-NEXT: ADD_INT T2.Z, T2.X, literal.z, +; R600-NEXT: SETGT_UINT * T1.W, T2.X, literal.w, ; R600-NEXT: 127(1.779649e-43), 204(2.858649e-43) ; R600-NEXT: 102(1.429324e-43), -229(nan) -; R600-NEXT: MIN_INT * T4.W, T3.X, literal.x, +; R600-NEXT: MIN_INT * T5.W, T2.X, literal.x, ; R600-NEXT: 381(5.338947e-43), 0(0.000000e+00) ; R600-NEXT: ADD_INT T5.X, PV.W, literal.x, -; R600-NEXT: ADD_INT T1.Y, T3.X, literal.y, -; R600-NEXT: SETGT_UINT T3.Z, T3.X, literal.z, -; R600-NEXT: CNDE_INT T4.W, T1.W, T0.Y, T2.Z, -; R600-NEXT: SETGT_INT * T5.W, T3.X, literal.y, +; R600-NEXT: ADD_INT T3.Y, T2.X, literal.y, +; R600-NEXT: SETGT_UINT T3.Z, T2.X, literal.z, +; R600-NEXT: CNDE_INT T5.W, T1.W, T2.Y, T2.Z, +; R600-NEXT: SETGT_INT * T6.W, T2.X, literal.y, ; R600-NEXT: -254(nan), -127(nan) ; R600-NEXT: 254(3.559298e-43), 0(0.000000e+00) -; R600-NEXT: CNDE_INT T6.X, PS, PV.W, T3.X, -; R600-NEXT: CNDE_INT T0.Y, PV.Z, PV.Y, PV.X, -; R600-NEXT: SETGT_INT T2.Z, T3.X, literal.x, -; R600-NEXT: CNDE_INT T0.W, T0.X, T1.Z, T0.W, BS:VEC_120/SCL_212 -; R600-NEXT: MUL_IEEE * T4.W, T2.Y, literal.y, -; R600-NEXT: 127(1.779649e-43), 2130706432(1.701412e+38) -; R600-NEXT: CNDE_INT T3.X, T2.W, T2.Y, PS, BS:VEC_120/SCL_212 -; R600-NEXT: LSHL T1.Y, PV.W, literal.x, -; R600-NEXT: CNDE_INT T1.Z, PV.Z, PV.X, PV.Y, -; R600-NEXT: MUL_IEEE T0.W, T4.X, literal.y, -; R600-NEXT: CNDE_INT * T1.W, T1.W, T2.X, T3.W, +; R600-NEXT: CNDE_INT T6.X, PS, PV.W, T2.X, +; R600-NEXT: CNDE_INT T2.Y, PV.Z, PV.Y, PV.X, +; R600-NEXT: SETGT_INT T2.Z, T2.X, literal.x, BS:VEC_120/SCL_212 +; R600-NEXT: CNDE_INT T3.W, T3.X, T1.Z, T3.W, BS:VEC_021/SCL_122 +; R600-NEXT: CNDE_INT * T0.W, T2.W, T4.Y, T0.W, +; R600-NEXT: 127(1.779649e-43), 0(0.000000e+00) +; R600-NEXT: CNDE_INT T0.X, T0.Z, PS, T0.X, +; R600-NEXT: LSHL T3.Y, PV.W, literal.x, +; R600-NEXT: CNDE_INT T0.Z, PV.Z, PV.X, PV.Y, +; R600-NEXT: CNDE_INT T0.W, T1.W, T4.X, T4.W, +; R600-NEXT: MUL_IEEE * T1.W, T1.Y, literal.y, ; R600-NEXT: 23(3.222986e-44), 2130706432(1.701412e+38) -; R600-NEXT: CNDE_INT T1.X, T5.W, PS, T1.X, BS:VEC_021/SCL_122 -; R600-NEXT: CNDE_INT T0.Y, T3.Z, T4.X, PV.W, BS:VEC_201 -; R600-NEXT: LSHL T1.Z, PV.Z, literal.x, +; R600-NEXT: CNDE_INT T2.X, T3.Z, T1.Y, PS, +; R600-NEXT: CNDE_INT T0.Y, T6.W, PV.W, T0.Y, +; R600-NEXT: LSHL T0.Z, PV.Z, literal.x, ; R600-NEXT: ADD_INT T0.W, PV.Y, literal.y, -; R600-NEXT: CNDE_INT * T1.W, T0.X, T0.Z, PV.X, +; R600-NEXT: CNDE_INT * T1.W, T3.X, PV.X, T1.X, ; R600-NEXT: 23(3.222986e-44), 1065353216(1.000000e+00) ; R600-NEXT: MUL_IEEE T1.Y, PS, PV.W, -; R600-NEXT: SETGT T0.Z, literal.x, KC0[3].X, +; R600-NEXT: SETGT T1.Z, literal.x, KC0[3].X, ; R600-NEXT: ADD_INT * T0.W, PV.Z, literal.y, ; R600-NEXT: -1036817932(-4.485347e+01), 1065353216(1.000000e+00) ; R600-NEXT: ALU clause starting at 101: -; R600-NEXT: CNDE_INT * T1.W, T2.Z, T1.X, T0.Y, +; R600-NEXT: CNDE_INT * T1.W, T2.Z, T0.Y, T2.X, ; R600-NEXT: MUL_IEEE T0.Y, PV.W, T0.W, -; R600-NEXT: SETGT T1.Z, literal.x, KC0[2].W, -; R600-NEXT: CNDE T0.W, T0.Z, T1.Y, 0.0, +; R600-NEXT: SETGT T0.Z, literal.x, KC0[2].W, +; R600-NEXT: CNDE T0.W, T1.Z, T1.Y, 0.0, ; R600-NEXT: SETGT * T1.W, KC0[3].X, literal.y, ; R600-NEXT: -1036817932(-4.485347e+01), 1109008539(3.853184e+01) ; R600-NEXT: CNDE T1.Y, PS, PV.W, literal.x, @@ -721,116 +723,118 @@ define amdgpu_kernel void @s_exp10_v2f32(ptr addrspace(1) %out, <2 x float> %in) ; ; CM-LABEL: s_exp10_v2f32: ; CM: ; %bb.0: -; CM-NEXT: ALU 98, @4, KC0[CB0:0-32], KC1[] -; CM-NEXT: ALU 18, @103, KC0[CB0:0-32], KC1[] +; CM-NEXT: ALU 100, @4, KC0[CB0:0-32], KC1[] +; CM-NEXT: ALU 18, @105, KC0[CB0:0-32], KC1[] ; CM-NEXT: MEM_RAT_CACHELESS STORE_DWORD T0, T1.X ; CM-NEXT: CF_END ; CM-NEXT: ALU clause starting at 4: ; CM-NEXT: AND_INT * T0.W, KC0[2].W, literal.x, ; CM-NEXT: -4096(nan), 0(0.000000e+00) +; CM-NEXT: MUL_IEEE T0.Z, PV.W, literal.x, ; CM-NEXT: ADD * T1.W, KC0[2].W, -PV.W, -; CM-NEXT: MUL_IEEE T0.Y, PV.W, literal.x, -; CM-NEXT: MUL_IEEE T0.Z, T0.W, literal.y, -; CM-NEXT: AND_INT * T2.W, KC0[3].X, literal.z, -; CM-NEXT: 975668412(6.390323e-04), 1079283712(3.321289e+00) -; CM-NEXT: -4096(nan), 0(0.000000e+00) -; CM-NEXT: ADD T1.Y, KC0[3].X, -PV.W, -; CM-NEXT: RNDNE T1.Z, PV.Z, -; CM-NEXT: MULADD_IEEE * T1.W, T1.W, literal.x, PV.Y, ; CM-NEXT: 1079283712(3.321289e+00), 0(0.000000e+00) +; CM-NEXT: MUL_IEEE T1.Z, PV.W, literal.x, +; CM-NEXT: RNDNE * T2.W, PV.Z, +; CM-NEXT: 975668412(6.390323e-04), 0(0.000000e+00) +; CM-NEXT: TRUNC T0.Y, PV.W, +; CM-NEXT: AND_INT T2.Z, KC0[3].X, literal.x, +; CM-NEXT: MULADD_IEEE * T1.W, T1.W, literal.y, PV.Z, +; CM-NEXT: -4096(nan), 1079283712(3.321289e+00) ; CM-NEXT: MULADD_IEEE T0.X, T0.W, literal.x, PV.W, -; CM-NEXT: ADD T0.Y, T0.Z, -PV.Z, -; CM-NEXT: MUL_IEEE T0.Z, PV.Y, literal.x, -; CM-NEXT: MUL_IEEE * T0.W, T2.W, literal.y, BS:VEC_120/SCL_212 +; CM-NEXT: MUL_IEEE T1.Y, PV.Z, literal.y, +; CM-NEXT: FLT_TO_INT T1.Z, PV.Y, +; CM-NEXT: ADD * T0.W, KC0[3].X, -PV.Z, ; CM-NEXT: 975668412(6.390323e-04), 1079283712(3.321289e+00) -; CM-NEXT: TRUNC T1.X, T1.Z, -; CM-NEXT: RNDNE T2.Y, PV.W, -; CM-NEXT: MULADD_IEEE T0.Z, T1.Y, literal.x, PV.Z, -; CM-NEXT: ADD * T1.W, PV.Y, PV.X, -; CM-NEXT: 1079283712(3.321289e+00), 0(0.000000e+00) -; CM-NEXT: EXP_IEEE T0.X, T1.W, -; CM-NEXT: EXP_IEEE T0.Y (MASKED), T1.W, -; CM-NEXT: EXP_IEEE T0.Z (MASKED), T1.W, -; CM-NEXT: EXP_IEEE * T0.W (MASKED), T1.W, -; CM-NEXT: MULADD_IEEE T2.X, T2.W, literal.x, T0.Z, -; CM-NEXT: ADD T0.Y, T0.W, -T2.Y, BS:VEC_120/SCL_212 -; CM-NEXT: FLT_TO_INT T0.Z, T1.X, -; CM-NEXT: MUL_IEEE * T0.W, PV.X, literal.y, -; CM-NEXT: 975668412(6.390323e-04), 209715200(1.972152e-31) -; CM-NEXT: MUL_IEEE T1.X, PV.W, literal.x, -; CM-NEXT: SETGT_UINT T1.Y, PV.Z, literal.y, -; CM-NEXT: TRUNC T1.Z, T2.Y, -; CM-NEXT: ADD * T1.W, PV.Y, PV.X, -; CM-NEXT: 209715200(1.972152e-31), -229(nan) +; CM-NEXT: ADD T1.X, T0.Z, -T2.W, +; CM-NEXT: MUL_IEEE T0.Y, PV.W, literal.x, +; CM-NEXT: MAX_INT T0.Z, PV.Z, literal.y, +; CM-NEXT: RNDNE * T1.W, PV.Y, +; CM-NEXT: 975668412(6.390323e-04), -330(nan) +; CM-NEXT: TRUNC T2.X, PV.W, +; CM-NEXT: ADD_INT T2.Y, PV.Z, literal.x, +; CM-NEXT: MULADD_IEEE T0.Z, T0.W, literal.y, PV.Y, +; CM-NEXT: ADD * T0.W, PV.X, T0.X, +; CM-NEXT: 204(2.858649e-43), 1079283712(3.321289e+00) +; CM-NEXT: EXP_IEEE T0.X, T0.W, +; CM-NEXT: EXP_IEEE T0.Y (MASKED), T0.W, +; CM-NEXT: EXP_IEEE T0.Z (MASKED), T0.W, +; CM-NEXT: EXP_IEEE * T0.W (MASKED), T0.W, +; CM-NEXT: ADD_INT T1.X, T1.Z, literal.x, +; CM-NEXT: MULADD_IEEE T0.Y, T2.Z, literal.y, T0.Z, BS:VEC_102/SCL_221 +; CM-NEXT: ADD T0.Z, T1.Y, -T1.W, +; CM-NEXT: MUL_IEEE * T0.W, PV.X, literal.z, +; CM-NEXT: 102(1.429324e-43), 975668412(6.390323e-04) +; CM-NEXT: 2130706432(1.701412e+38), 0(0.000000e+00) +; CM-NEXT: SETGT_UINT T3.X, T1.Z, literal.x, +; CM-NEXT: MUL_IEEE T1.Y, PV.W, literal.y, +; CM-NEXT: SETGT_UINT T2.Z, T1.Z, literal.z, +; CM-NEXT: ADD * T1.W, PV.Z, PV.Y, +; CM-NEXT: -229(nan), 2130706432(1.701412e+38) +; CM-NEXT: 254(3.559298e-43), 0(0.000000e+00) ; CM-NEXT: EXP_IEEE T0.X (MASKED), T1.W, ; CM-NEXT: EXP_IEEE T0.Y, T1.W, ; CM-NEXT: EXP_IEEE T0.Z (MASKED), T1.W, ; CM-NEXT: EXP_IEEE * T0.W (MASKED), T1.W, -; CM-NEXT: FLT_TO_INT T2.X, T1.Z, -; CM-NEXT: MUL_IEEE T2.Y, PV.Y, literal.x, -; CM-NEXT: CNDE_INT T1.Z, T1.Y, T1.X, T0.W, -; CM-NEXT: SETGT_INT * T0.W, T0.Z, literal.y, BS:VEC_120/SCL_212 -; CM-NEXT: 209715200(1.972152e-31), -127(nan) -; CM-NEXT: CNDE_INT T1.X, PV.W, PV.Z, T0.X, +; CM-NEXT: CNDE_INT T4.X, T2.Z, T0.W, T1.Y, +; CM-NEXT: CNDE_INT T1.Y, T3.X, T2.Y, T1.X, +; CM-NEXT: FLT_TO_INT T0.Z, T2.X, BS:VEC_120/SCL_212 +; CM-NEXT: MUL_IEEE * T0.W, PV.Y, literal.x, +; CM-NEXT: 2130706432(1.701412e+38), 0(0.000000e+00) +; CM-NEXT: SETGT_INT T1.X, T1.Z, literal.x, +; CM-NEXT: MUL_IEEE T2.Y, T0.X, literal.y, +; CM-NEXT: MUL_IEEE T3.Z, PV.W, literal.z, +; CM-NEXT: SETGT_UINT * T1.W, PV.Z, literal.w, +; CM-NEXT: -127(nan), 209715200(1.972152e-31) +; CM-NEXT: 2130706432(1.701412e+38), 254(3.559298e-43) +; CM-NEXT: CNDE_INT T2.X, PV.W, T0.W, PV.Z, ; CM-NEXT: MUL_IEEE T3.Y, PV.Y, literal.x, -; CM-NEXT: SETGT_UINT T1.Z, PV.X, literal.y, -; CM-NEXT: MAX_INT * T1.W, T0.Z, literal.z, -; CM-NEXT: 209715200(1.972152e-31), -229(nan) -; CM-NEXT: -330(nan), 0(0.000000e+00) -; CM-NEXT: ADD_INT T3.X, PV.W, literal.x, -; CM-NEXT: ADD_INT T4.Y, T0.Z, literal.y, -; CM-NEXT: CNDE_INT T2.Z, PV.Z, PV.Y, T2.Y, -; CM-NEXT: SETGT_INT * T1.W, T2.X, literal.z, +; CM-NEXT: CNDE_INT T3.Z, PV.X, T1.Y, T1.Z, +; CM-NEXT: MAX_INT * T0.W, T0.Z, literal.y, +; CM-NEXT: 209715200(1.972152e-31), -330(nan) +; CM-NEXT: ADD_INT T5.X, PV.W, literal.x, +; CM-NEXT: ADD_INT T1.Y, T0.Z, literal.y, +; CM-NEXT: SETGT_UINT T4.Z, T0.Z, literal.z, +; CM-NEXT: MUL_IEEE * T0.W, T0.Y, literal.w, ; CM-NEXT: 204(2.858649e-43), 102(1.429324e-43) +; CM-NEXT: -229(nan), 209715200(1.972152e-31) +; CM-NEXT: MUL_IEEE T6.X, PV.W, literal.x, +; CM-NEXT: MIN_INT T4.Y, T0.Z, literal.y, +; CM-NEXT: CNDE_INT T5.Z, PV.Z, PV.X, PV.Y, +; CM-NEXT: SETGT_INT * T2.W, T0.Z, literal.z, +; CM-NEXT: 209715200(1.972152e-31), 381(5.338947e-43) ; CM-NEXT: -127(nan), 0(0.000000e+00) -; CM-NEXT: CNDE_INT T4.X, PV.W, PV.Z, T0.Y, -; CM-NEXT: MUL_IEEE T2.Y, T0.X, literal.x, -; CM-NEXT: MAX_INT T2.Z, T2.X, literal.y, BS:VEC_120/SCL_212 -; CM-NEXT: CNDE_INT * T2.W, T1.Y, PV.X, PV.Y, -; CM-NEXT: 2130706432(1.701412e+38), -330(nan) -; CM-NEXT: CNDE_INT T0.X, T0.W, PV.W, T0.Z, -; CM-NEXT: ADD_INT T1.Y, PV.Z, literal.x, -; CM-NEXT: ADD_INT T2.Z, T2.X, literal.y, -; CM-NEXT: MIN_INT * T0.W, T2.X, literal.z, -; CM-NEXT: 204(2.858649e-43), 102(1.429324e-43) -; CM-NEXT: 381(5.338947e-43), 0(0.000000e+00) -; CM-NEXT: ADD_INT T3.X, PV.W, literal.x, -; CM-NEXT: ADD_INT T3.Y, T2.X, literal.y, -; CM-NEXT: SETGT_UINT T3.Z, T2.X, literal.z, -; CM-NEXT: CNDE_INT * T0.W, T1.Z, PV.Y, PV.Z, -; CM-NEXT: -254(nan), -127(nan) -; CM-NEXT: 254(3.559298e-43), 0(0.000000e+00) -; CM-NEXT: MUL_IEEE T5.X, T0.Y, literal.x, -; CM-NEXT: CNDE_INT T0.Y, T1.W, PV.W, T2.X, -; CM-NEXT: CNDE_INT T1.Z, PV.Z, PV.Y, PV.X, -; CM-NEXT: MIN_INT * T0.W, T0.Z, literal.y, -; CM-NEXT: 2130706432(1.701412e+38), 381(5.338947e-43) -; CM-NEXT: SETGT_INT T2.X, T2.X, literal.x, -; CM-NEXT: ADD_INT T1.Y, PV.W, literal.y, -; CM-NEXT: ADD_INT T2.Z, T0.Z, literal.z, -; CM-NEXT: SETGT_UINT * T0.W, T0.Z, literal.w, +; CM-NEXT: CNDE_INT T5.X, PV.W, PV.Z, T0.Z, +; CM-NEXT: MIN_INT T1.Y, T1.Z, literal.x, +; CM-NEXT: ADD_INT T5.Z, PV.Y, literal.y, +; CM-NEXT: ADD_INT * T3.W, T0.Z, literal.z, BS:VEC_120/SCL_212 +; CM-NEXT: 381(5.338947e-43), -254(nan) +; CM-NEXT: -127(nan), 0(0.000000e+00) +; CM-NEXT: CNDE_INT T7.X, T1.W, PV.W, PV.Z, +; CM-NEXT: SETGT_INT T4.Y, T0.Z, literal.x, +; CM-NEXT: ADD_INT T0.Z, PV.Y, literal.y, +; CM-NEXT: ADD_INT * T1.W, T1.Z, literal.z, BS:VEC_120/SCL_212 ; CM-NEXT: 127(1.779649e-43), -254(nan) -; CM-NEXT: -127(nan), 254(3.559298e-43) -; CM-NEXT: CNDE_INT T3.X, PV.W, PV.Z, PV.Y, -; CM-NEXT: SETGT_INT T1.Y, T0.Z, literal.x, -; CM-NEXT: CNDE_INT T0.Z, PV.X, T0.Y, T1.Z, -; CM-NEXT: MUL_IEEE * T1.W, T5.X, literal.y, -; CM-NEXT: 127(1.779649e-43), 2130706432(1.701412e+38) -; CM-NEXT: CNDE_INT T5.X, T3.Z, T5.X, PV.W, +; CM-NEXT: -127(nan), 0(0.000000e+00) +; CM-NEXT: CNDE_INT T8.X, T2.Z, PV.W, PV.Z, +; CM-NEXT: SETGT_INT T1.Y, T1.Z, literal.x, BS:VEC_120/SCL_212 +; CM-NEXT: CNDE_INT T0.Z, PV.Y, T5.X, PV.X, +; CM-NEXT: CNDE_INT * T0.W, T4.Z, T6.X, T0.W, BS:VEC_201 +; CM-NEXT: 127(1.779649e-43), 0(0.000000e+00) +; CM-NEXT: CNDE_INT T5.X, T2.W, PV.W, T0.Y, ; CM-NEXT: LSHL T0.Y, PV.Z, literal.x, -; CM-NEXT: CNDE_INT T0.Z, PV.Y, T0.X, PV.X, BS:VEC_021/SCL_122 -; CM-NEXT: MUL_IEEE * T1.W, T2.Y, literal.y, -; CM-NEXT: 23(3.222986e-44), 2130706432(1.701412e+38) -; CM-NEXT: CNDE_INT T0.X, T0.W, T2.Y, PV.W, +; CM-NEXT: CNDE_INT T0.Z, PV.Y, T3.Z, PV.X, +; CM-NEXT: CNDE_INT * T0.W, T3.X, T3.Y, T2.Y, BS:VEC_201 +; CM-NEXT: 23(3.222986e-44), 0(0.000000e+00) +; CM-NEXT: CNDE_INT T0.X, T1.X, PV.W, T0.X, ; CM-NEXT: LSHL T2.Y, PV.Z, literal.x, ; CM-NEXT: ADD_INT * T0.Z, PV.Y, literal.y, ; CM-NEXT: 23(3.222986e-44), 1065353216(1.000000e+00) -; CM-NEXT: ALU clause starting at 103: -; CM-NEXT: CNDE_INT * T0.W, T2.X, T4.X, T5.X, -; CM-NEXT: MUL_IEEE T2.X, PV.W, T0.Z, +; CM-NEXT: ALU clause starting at 105: +; CM-NEXT: CNDE_INT * T0.W, T4.Y, T5.X, T2.X, +; CM-NEXT: MUL_IEEE T1.X, PV.W, T0.Z, ; CM-NEXT: SETGT T0.Y, literal.x, KC0[3].X, ; CM-NEXT: ADD_INT T0.Z, T2.Y, literal.y, -; CM-NEXT: CNDE_INT * T0.W, T1.Y, T1.X, T0.X, BS:VEC_120/SCL_212 +; CM-NEXT: CNDE_INT * T0.W, T1.Y, T0.X, T4.X, BS:VEC_120/SCL_212 ; CM-NEXT: -1036817932(-4.485347e+01), 1065353216(1.000000e+00) ; CM-NEXT: MUL_IEEE T0.X, PV.W, PV.Z, ; CM-NEXT: SETGT T1.Y, literal.x, KC0[2].W, @@ -1213,8 +1217,8 @@ define amdgpu_kernel void @s_exp10_v3f32(ptr addrspace(1) %out, <3 x float> %in) ; ; R600-LABEL: s_exp10_v3f32: ; R600: ; %bb.0: -; R600-NEXT: ALU 99, @6, KC0[CB0:0-32], KC1[] -; R600-NEXT: ALU 69, @106, KC0[CB0:0-32], KC1[] +; R600-NEXT: ALU 100, @6, KC0[CB0:0-32], KC1[] +; R600-NEXT: ALU 69, @107, KC0[CB0:0-32], KC1[] ; R600-NEXT: MEM_RAT_CACHELESS STORE_RAW T2.X, T3.X, 0 ; R600-NEXT: MEM_RAT_CACHELESS STORE_RAW T0.XY, T1.X, 1 ; R600-NEXT: CF_END @@ -1222,68 +1226,69 @@ define amdgpu_kernel void @s_exp10_v3f32(ptr addrspace(1) %out, <3 x float> %in) ; R600-NEXT: ALU clause starting at 6: ; R600-NEXT: AND_INT * T0.W, KC0[3].Y, literal.x, ; R600-NEXT: -4096(nan), 0(0.000000e+00) -; R600-NEXT: MUL_IEEE T1.W, PV.W, literal.x, -; R600-NEXT: ADD * T2.W, KC0[3].Y, -PV.W, +; R600-NEXT: ADD T1.W, KC0[3].Y, -PV.W, +; R600-NEXT: MUL_IEEE * T2.W, PV.W, literal.x, ; R600-NEXT: 1079283712(3.321289e+00), 0(0.000000e+00) -; R600-NEXT: RNDNE * T3.W, PV.W, -; R600-NEXT: TRUNC T4.W, PV.W, -; R600-NEXT: MUL_IEEE * T5.W, T2.W, literal.x, +; R600-NEXT: RNDNE T3.W, PS, +; R600-NEXT: MUL_IEEE * T4.W, PV.W, literal.x, ; R600-NEXT: 975668412(6.390323e-04), 0(0.000000e+00) -; R600-NEXT: MULADD_IEEE T2.W, T2.W, literal.x, PS, -; R600-NEXT: FLT_TO_INT * T4.W, PV.W, +; R600-NEXT: MULADD_IEEE T1.W, T1.W, literal.x, PS, +; R600-NEXT: TRUNC * T4.W, PV.W, ; R600-NEXT: 1079283712(3.321289e+00), 0(0.000000e+00) -; R600-NEXT: MAX_INT T0.Z, PS, literal.x, -; R600-NEXT: MULADD_IEEE T0.W, T0.W, literal.y, PV.W, -; R600-NEXT: ADD * T1.W, T1.W, -T3.W, -; R600-NEXT: -330(nan), 975668412(6.390323e-04) -; R600-NEXT: ADD T0.Y, PS, PV.W, -; R600-NEXT: ADD_INT T0.Z, PV.Z, literal.x, -; R600-NEXT: ADD_INT T0.W, T4.W, literal.y, -; R600-NEXT: SETGT_UINT * T1.W, T4.W, literal.z, +; R600-NEXT: FLT_TO_INT T0.Z, PS, +; R600-NEXT: MULADD_IEEE T0.W, T0.W, literal.x, PV.W, +; R600-NEXT: ADD * T1.W, T2.W, -T3.W, +; R600-NEXT: 975668412(6.390323e-04), 0(0.000000e+00) +; R600-NEXT: ADD T0.W, PS, PV.W, +; R600-NEXT: MAX_INT * T1.W, PV.Z, literal.x, +; R600-NEXT: -330(nan), 0(0.000000e+00) +; R600-NEXT: ADD_INT T0.Y, PS, literal.x, +; R600-NEXT: ADD_INT T1.Z, T0.Z, literal.y, +; R600-NEXT: SETGT_UINT T1.W, T0.Z, literal.z, +; R600-NEXT: EXP_IEEE * T0.X, PV.W, ; R600-NEXT: 204(2.858649e-43), 102(1.429324e-43) ; R600-NEXT: -229(nan), 0(0.000000e+00) -; R600-NEXT: CNDE_INT T0.Z, PS, PV.Z, PV.W, -; R600-NEXT: SETGT_INT T0.W, T4.W, literal.x, -; R600-NEXT: EXP_IEEE * T0.X, PV.Y, -; R600-NEXT: -127(nan), 0(0.000000e+00) -; R600-NEXT: MUL_IEEE T1.X, PS, literal.x, -; R600-NEXT: CNDE_INT T0.Y, PV.W, PV.Z, T4.W, -; R600-NEXT: MIN_INT T0.Z, T4.W, literal.y, -; R600-NEXT: AND_INT T2.W, KC0[3].W, literal.z, -; R600-NEXT: MUL_IEEE * T3.W, PS, literal.w, -; R600-NEXT: 2130706432(1.701412e+38), 381(5.338947e-43) -; R600-NEXT: -4096(nan), 209715200(1.972152e-31) -; R600-NEXT: MUL_IEEE T2.X, PS, literal.x, -; R600-NEXT: ADD T1.Y, KC0[3].W, -PV.W, -; R600-NEXT: ADD_INT T0.Z, PV.Z, literal.y, -; R600-NEXT: ADD_INT T5.W, T4.W, literal.z, -; R600-NEXT: SETGT_UINT * T6.W, T4.W, literal.w, -; R600-NEXT: 209715200(1.972152e-31), -254(nan) +; R600-NEXT: CNDE_INT T1.Z, PV.W, PV.Y, PV.Z, +; R600-NEXT: SETGT_INT T0.W, T0.Z, literal.x, +; R600-NEXT: MUL_IEEE * T2.W, PS, literal.y, +; R600-NEXT: -127(nan), 209715200(1.972152e-31) +; R600-NEXT: MUL_IEEE T0.Y, PS, literal.x, +; R600-NEXT: CNDE_INT T1.Z, PV.W, PV.Z, T0.Z, +; R600-NEXT: MIN_INT T3.W, T0.Z, literal.y, +; R600-NEXT: AND_INT * T4.W, KC0[3].W, literal.z, +; R600-NEXT: 209715200(1.972152e-31), 381(5.338947e-43) +; R600-NEXT: -4096(nan), 0(0.000000e+00) +; R600-NEXT: MUL_IEEE T1.X, T0.X, literal.x, +; R600-NEXT: ADD T1.Y, KC0[3].W, -PS, +; R600-NEXT: ADD_INT T2.Z, PV.W, literal.y, +; R600-NEXT: ADD_INT T3.W, T0.Z, literal.z, +; R600-NEXT: SETGT_UINT * T5.W, T0.Z, literal.w, +; R600-NEXT: 2130706432(1.701412e+38), -254(nan) ; R600-NEXT: -127(nan), 254(3.559298e-43) -; R600-NEXT: CNDE_INT T3.X, PS, PV.W, PV.Z, -; R600-NEXT: SETGT_INT T2.Y, T4.W, literal.x, +; R600-NEXT: CNDE_INT T2.X, PS, PV.W, PV.Z, +; R600-NEXT: SETGT_INT T2.Y, T0.Z, literal.x, ; R600-NEXT: MUL_IEEE T0.Z, PV.Y, literal.y, -; R600-NEXT: MUL_IEEE * T4.W, T2.W, literal.z, BS:VEC_120/SCL_212 +; R600-NEXT: MUL_IEEE T3.W, T4.W, literal.z, +; R600-NEXT: MUL_IEEE * T6.W, PV.X, literal.w, ; R600-NEXT: 127(1.779649e-43), 975668412(6.390323e-04) -; R600-NEXT: 1079283712(3.321289e+00), 0(0.000000e+00) -; R600-NEXT: CNDE_INT * T1.W, T1.W, T2.X, T3.W, -; R600-NEXT: CNDE_INT T0.X, T0.W, PV.W, T0.X, BS:VEC_021/SCL_122 -; R600-NEXT: RNDNE T3.Y, T4.W, BS:VEC_120/SCL_212 -; R600-NEXT: MULADD_IEEE T0.Z, T1.Y, literal.x, T0.Z, -; R600-NEXT: CNDE_INT T0.W, T2.Y, T0.Y, T3.X, BS:VEC_120/SCL_212 -; R600-NEXT: MUL_IEEE * T1.W, T1.X, literal.y, ; R600-NEXT: 1079283712(3.321289e+00), 2130706432(1.701412e+38) -; R600-NEXT: CNDE_INT T1.X, T6.W, T1.X, PS, +; R600-NEXT: CNDE_INT T1.X, T5.W, T1.X, PS, BS:VEC_120/SCL_212 +; R600-NEXT: RNDNE T3.Y, PV.W, +; R600-NEXT: MULADD_IEEE T0.Z, T1.Y, literal.x, PV.Z, +; R600-NEXT: CNDE_INT T5.W, PV.Y, T1.Z, PV.X, +; R600-NEXT: CNDE_INT * T1.W, T1.W, T0.Y, T2.W, +; R600-NEXT: 1079283712(3.321289e+00), 0(0.000000e+00) +; R600-NEXT: CNDE_INT T0.X, T0.W, PS, T0.X, ; R600-NEXT: LSHL T0.Y, PV.W, literal.x, ; R600-NEXT: AND_INT T1.Z, KC0[3].Z, literal.y, -; R600-NEXT: MULADD_IEEE T0.W, T2.W, literal.z, PV.Z, BS:VEC_120/SCL_212 -; R600-NEXT: ADD * T1.W, T4.W, -PV.Y, +; R600-NEXT: MULADD_IEEE T0.W, T4.W, literal.z, PV.Z, BS:VEC_120/SCL_212 +; R600-NEXT: ADD * T1.W, T3.W, -PV.Y, ; R600-NEXT: 23(3.222986e-44), -4096(nan) ; R600-NEXT: 975668412(6.390323e-04), 0(0.000000e+00) ; R600-NEXT: ADD T1.Y, PS, PV.W, ; R600-NEXT: MUL_IEEE T0.Z, PV.Z, literal.x, ; R600-NEXT: ADD_INT T0.W, PV.Y, literal.y, -; R600-NEXT: CNDE_INT * T1.W, T2.Y, T0.X, PV.X, +; R600-NEXT: CNDE_INT * T1.W, T2.Y, PV.X, T1.X, ; R600-NEXT: 1079283712(3.321289e+00), 1065353216(1.000000e+00) ; R600-NEXT: MUL_IEEE T0.X, PS, PV.W, ; R600-NEXT: ADD T0.Y, KC0[3].Z, -T1.Z, @@ -1297,12 +1302,12 @@ define amdgpu_kernel void @s_exp10_v3f32(ptr addrspace(1) %out, <3 x float> %in) ; R600-NEXT: MUL_IEEE * T1.W, PS, literal.z, ; R600-NEXT: -1036817932(-4.485347e+01), 975668412(6.390323e-04) ; R600-NEXT: 209715200(1.972152e-31), 0(0.000000e+00) -; R600-NEXT: MUL_IEEE T3.X, PS, literal.x, -; R600-NEXT: MUL_IEEE T2.Y, T1.X, literal.y, +; R600-NEXT: MUL_IEEE T3.X, T1.X, literal.x, +; R600-NEXT: MUL_IEEE T2.Y, PS, literal.y, ; R600-NEXT: MULADD_IEEE T4.Z, T0.Y, literal.z, PV.W, ; R600-NEXT: FLT_TO_INT T0.W, PV.Z, ; R600-NEXT: MIN_INT * T2.W, PV.Y, literal.w, -; R600-NEXT: 209715200(1.972152e-31), 2130706432(1.701412e+38) +; R600-NEXT: 2130706432(1.701412e+38), 209715200(1.972152e-31) ; R600-NEXT: 1079283712(3.321289e+00), 381(5.338947e-43) ; R600-NEXT: ADD_INT T4.X, PS, literal.x, ; R600-NEXT: MAX_INT T0.Y, PV.W, literal.y, @@ -1320,7 +1325,7 @@ define amdgpu_kernel void @s_exp10_v3f32(ptr addrspace(1) %out, <3 x float> %in) ; R600-NEXT: 102(1.429324e-43), -229(nan) ; R600-NEXT: ADD_INT * T6.X, T0.W, literal.x, ; R600-NEXT: -127(nan), 0(0.000000e+00) -; R600-NEXT: ALU clause starting at 106: +; R600-NEXT: ALU clause starting at 107: ; R600-NEXT: SETGT_UINT T0.Y, T0.W, literal.x, ; R600-NEXT: CNDE_INT T0.Z, T3.W, T0.Z, T2.W, BS:VEC_102/SCL_221 ; R600-NEXT: SETGT_INT T2.W, T0.W, literal.y, @@ -1336,25 +1341,25 @@ define amdgpu_kernel void @s_exp10_v3f32(ptr addrspace(1) %out, <3 x float> %in) ; R600-NEXT: SETGT_UINT T5.X, T1.Y, literal.x, ; R600-NEXT: CNDE_INT T4.Y, PS, PV.Z, PV.W, ; R600-NEXT: MAX_INT T0.Z, T1.Y, literal.y, -; R600-NEXT: MUL_IEEE T4.W, PV.Y, literal.z, -; R600-NEXT: MUL_IEEE * T5.W, T1.Z, literal.w, +; R600-NEXT: MUL_IEEE T4.W, T1.Z, literal.z, +; R600-NEXT: MUL_IEEE * T5.W, PV.Y, literal.w, ; R600-NEXT: 254(3.559298e-43), -330(nan) -; R600-NEXT: 209715200(1.972152e-31), 2130706432(1.701412e+38) -; R600-NEXT: MUL_IEEE T6.X, PS, literal.x, -; R600-NEXT: CNDE_INT T3.Y, T3.W, PV.W, T3.Y, BS:VEC_021/SCL_122 +; R600-NEXT: 2130706432(1.701412e+38), 209715200(1.972152e-31) +; R600-NEXT: CNDE_INT T6.X, T3.W, PS, T3.Y, BS:VEC_021/SCL_122 +; R600-NEXT: MUL_IEEE T3.Y, PV.W, literal.x, ; R600-NEXT: ADD_INT T0.Z, PV.Z, literal.y, ; R600-NEXT: ADD_INT T3.W, T1.Y, literal.z, -; R600-NEXT: SETGT_UINT * T4.W, T1.Y, literal.w, +; R600-NEXT: SETGT_UINT * T5.W, T1.Y, literal.w, ; R600-NEXT: 2130706432(1.701412e+38), 204(2.858649e-43) ; R600-NEXT: 102(1.429324e-43), -229(nan) ; R600-NEXT: CNDE_INT T8.X, PS, PV.Z, PV.W, ; R600-NEXT: SETGT_INT T5.Y, T1.Y, literal.x, -; R600-NEXT: CNDE_INT T0.Z, T2.W, PV.Y, T1.Z, -; R600-NEXT: CNDE_INT T2.W, T0.Y, T5.W, PV.X, BS:VEC_120/SCL_212 +; R600-NEXT: CNDE_INT T0.Z, T0.Y, T4.W, PV.Y, BS:VEC_120/SCL_212 +; R600-NEXT: CNDE_INT T2.W, T2.W, PV.X, T1.Z, ; R600-NEXT: LSHL * T3.W, T4.Y, literal.y, ; R600-NEXT: -127(nan), 23(3.222986e-44) ; R600-NEXT: ADD_INT T6.X, PS, literal.x, -; R600-NEXT: CNDE_INT T0.Y, T0.W, PV.Z, PV.W, +; R600-NEXT: CNDE_INT T0.Y, T0.W, PV.W, PV.Z, ; R600-NEXT: CNDE_INT T0.Z, PV.Y, PV.X, T1.Y, ; R600-NEXT: CNDE_INT T0.W, T5.X, T7.X, T4.X, ; R600-NEXT: SETGT_INT * T2.W, T1.Y, literal.y, @@ -1362,18 +1367,18 @@ define amdgpu_kernel void @s_exp10_v3f32(ptr addrspace(1) %out, <3 x float> %in) ; R600-NEXT: CNDE_INT T4.X, PS, PV.Z, PV.W, ; R600-NEXT: MUL_IEEE T0.Y, PV.Y, PV.X, ; R600-NEXT: SETGT T0.Z, literal.x, KC0[3].Z, -; R600-NEXT: MUL_IEEE T0.W, T2.Y, literal.y, -; R600-NEXT: CNDE_INT * T1.W, T4.W, T3.X, T1.W, +; R600-NEXT: CNDE_INT T0.W, T5.W, T2.Y, T1.W, +; R600-NEXT: MUL_IEEE * T1.W, T3.X, literal.y, ; R600-NEXT: -1036817932(-4.485347e+01), 2130706432(1.701412e+38) -; R600-NEXT: CNDE_INT T1.X, T5.Y, PS, T1.X, -; R600-NEXT: CNDE_INT T1.Y, T5.X, T2.Y, PV.W, +; R600-NEXT: CNDE_INT T3.X, T5.X, T3.X, PS, +; R600-NEXT: CNDE_INT T1.Y, T5.Y, PV.W, T1.X, ; R600-NEXT: CNDE T0.Z, PV.Z, PV.Y, 0.0, ; R600-NEXT: SETGT T0.W, KC0[3].Z, literal.x, ; R600-NEXT: LSHL * T1.W, PV.X, literal.y, ; R600-NEXT: 1109008539(3.853184e+01), 23(3.222986e-44) -; R600-NEXT: ADD_INT T3.X, PS, literal.x, +; R600-NEXT: ADD_INT T1.X, PS, literal.x, ; R600-NEXT: CNDE T0.Y, PV.W, PV.Z, literal.y, -; R600-NEXT: CNDE_INT T0.Z, T2.W, PV.X, PV.Y, +; R600-NEXT: CNDE_INT T0.Z, T2.W, PV.Y, PV.X, ; R600-NEXT: CNDE T0.W, T2.X, T0.X, 0.0, ; R600-NEXT: SETGT * T1.W, KC0[3].Y, literal.z, ; R600-NEXT: 1065353216(1.000000e+00), 2139095040(INF) @@ -1394,193 +1399,197 @@ define amdgpu_kernel void @s_exp10_v3f32(ptr addrspace(1) %out, <3 x float> %in) ; ; CM-LABEL: s_exp10_v3f32: ; CM: ; %bb.0: -; CM-NEXT: ALU 101, @6, KC0[CB0:0-32], KC1[] -; CM-NEXT: ALU 77, @108, KC0[CB0:0-32], KC1[] -; CM-NEXT: MEM_RAT_CACHELESS STORE_DWORD T0, T1.X -; CM-NEXT: MEM_RAT_CACHELESS STORE_DWORD T2.X, T3.X +; CM-NEXT: ALU 102, @6, KC0[CB0:0-32], KC1[] +; CM-NEXT: ALU 80, @109, KC0[CB0:0-32], KC1[] +; CM-NEXT: MEM_RAT_CACHELESS STORE_DWORD T1, T3.X +; CM-NEXT: MEM_RAT_CACHELESS STORE_DWORD T2.X, T0.X ; CM-NEXT: CF_END ; CM-NEXT: PAD ; CM-NEXT: ALU clause starting at 6: ; CM-NEXT: AND_INT * T0.W, KC0[3].Y, literal.x, ; CM-NEXT: -4096(nan), 0(0.000000e+00) -; CM-NEXT: ADD * T1.W, KC0[3].Y, -PV.W, ; CM-NEXT: MUL_IEEE T0.Z, PV.W, literal.x, -; CM-NEXT: MUL_IEEE * T2.W, T0.W, literal.y, -; CM-NEXT: 975668412(6.390323e-04), 1079283712(3.321289e+00) -; CM-NEXT: RNDNE T1.Z, PV.W, +; CM-NEXT: ADD * T1.W, KC0[3].Y, -PV.W, +; CM-NEXT: 1079283712(3.321289e+00), 0(0.000000e+00) +; CM-NEXT: MUL_IEEE T1.Z, PV.W, literal.x, +; CM-NEXT: RNDNE * T2.W, PV.Z, +; CM-NEXT: 975668412(6.390323e-04), 0(0.000000e+00) +; CM-NEXT: TRUNC T2.Z, PV.W, ; CM-NEXT: MULADD_IEEE * T1.W, T1.W, literal.x, PV.Z, ; CM-NEXT: 1079283712(3.321289e+00), 0(0.000000e+00) -; CM-NEXT: MULADD_IEEE T0.Z, T0.W, literal.x, PV.W, -; CM-NEXT: ADD * T0.W, T2.W, -PV.Z, BS:VEC_120/SCL_212 +; CM-NEXT: MULADD_IEEE T0.Y, T0.W, literal.x, PV.W, +; CM-NEXT: ADD T0.Z, T0.Z, -T2.W, +; CM-NEXT: FLT_TO_INT * T0.W, PV.Z, ; CM-NEXT: 975668412(6.390323e-04), 0(0.000000e+00) -; CM-NEXT: TRUNC T1.Z, T1.Z, -; CM-NEXT: ADD * T0.W, PV.W, PV.Z, -; CM-NEXT: EXP_IEEE T0.X, T0.W, -; CM-NEXT: EXP_IEEE T0.Y (MASKED), T0.W, -; CM-NEXT: EXP_IEEE T0.Z (MASKED), T0.W, -; CM-NEXT: EXP_IEEE * T0.W (MASKED), T0.W, -; CM-NEXT: FLT_TO_INT T0.Z, T1.Z, -; CM-NEXT: MUL_IEEE * T0.W, PV.X, literal.x, -; CM-NEXT: 209715200(1.972152e-31), 0(0.000000e+00) -; CM-NEXT: MUL_IEEE T0.Y, PV.W, literal.x, -; CM-NEXT: MAX_INT T1.Z, PV.Z, literal.y, -; CM-NEXT: MIN_INT * T1.W, PV.Z, literal.z, -; CM-NEXT: 209715200(1.972152e-31), -330(nan) +; CM-NEXT: MIN_INT T1.Z, PV.W, literal.x, +; CM-NEXT: ADD * T1.W, PV.Z, PV.Y, ; CM-NEXT: 381(5.338947e-43), 0(0.000000e+00) -; CM-NEXT: ADD_INT T1.X, PV.W, literal.x, -; CM-NEXT: ADD_INT T1.Y, PV.Z, literal.y, -; CM-NEXT: ADD_INT T1.Z, T0.Z, literal.z, -; CM-NEXT: SETGT_UINT * T1.W, T0.Z, literal.w, -; CM-NEXT: -254(nan), 204(2.858649e-43) +; CM-NEXT: EXP_IEEE T0.X, T1.W, +; CM-NEXT: EXP_IEEE T0.Y (MASKED), T1.W, +; CM-NEXT: EXP_IEEE T0.Z (MASKED), T1.W, +; CM-NEXT: EXP_IEEE * T0.W (MASKED), T1.W, +; CM-NEXT: MUL_IEEE T0.Y, PV.X, literal.x, +; CM-NEXT: ADD_INT T0.Z, T1.Z, literal.y, +; CM-NEXT: MAX_INT * T1.W, T0.W, literal.z, +; CM-NEXT: 2130706432(1.701412e+38), -254(nan) +; CM-NEXT: -330(nan), 0(0.000000e+00) +; CM-NEXT: ADD_INT T1.X, T0.W, literal.x, +; CM-NEXT: ADD_INT T1.Y, PV.W, literal.y, +; CM-NEXT: ADD_INT T1.Z, T0.W, literal.z, +; CM-NEXT: SETGT_UINT * T1.W, T0.W, literal.w, +; CM-NEXT: -127(nan), 204(2.858649e-43) ; CM-NEXT: 102(1.429324e-43), -229(nan) -; CM-NEXT: ADD_INT T2.X, T0.Z, literal.x, -; CM-NEXT: SETGT_UINT T2.Y, T0.Z, literal.y, -; CM-NEXT: CNDE_INT T1.Z, PV.W, PV.Y, PV.Z, -; CM-NEXT: SETGT_INT * T2.W, T0.Z, literal.x, -; CM-NEXT: -127(nan), 254(3.559298e-43) -; CM-NEXT: MUL_IEEE T3.X, T0.X, literal.x, -; CM-NEXT: CNDE_INT T1.Y, PV.W, PV.Z, T0.Z, -; CM-NEXT: CNDE_INT T1.Z, PV.Y, PV.X, T1.X, -; CM-NEXT: SETGT_INT * T3.W, T0.Z, literal.y, -; CM-NEXT: 2130706432(1.701412e+38), 127(1.779649e-43) +; CM-NEXT: SETGT_UINT T2.X, T0.W, literal.x, +; CM-NEXT: CNDE_INT T1.Y, PV.W, PV.Y, PV.Z, +; CM-NEXT: SETGT_INT T1.Z, T0.W, literal.y, +; CM-NEXT: MUL_IEEE * T2.W, T0.X, literal.z, +; CM-NEXT: 254(3.559298e-43), -127(nan) +; CM-NEXT: 209715200(1.972152e-31), 0(0.000000e+00) +; CM-NEXT: MUL_IEEE T3.X, PV.W, literal.x, +; CM-NEXT: CNDE_INT T1.Y, PV.Z, PV.Y, T0.W, +; CM-NEXT: CNDE_INT T0.Z, PV.X, T1.X, T0.Z, +; CM-NEXT: SETGT_INT * T0.W, T0.W, literal.y, +; CM-NEXT: 209715200(1.972152e-31), 127(1.779649e-43) ; CM-NEXT: CNDE_INT T1.Y, PV.W, PV.Y, PV.Z, -; CM-NEXT: MUL_IEEE T0.Z, PV.X, literal.x, -; CM-NEXT: CNDE_INT * T0.W, T1.W, T0.Y, T0.W, +; CM-NEXT: CNDE_INT T0.Z, T1.W, PV.X, T2.W, +; CM-NEXT: MUL_IEEE * T1.W, T0.Y, literal.x, ; CM-NEXT: 2130706432(1.701412e+38), 0(0.000000e+00) -; CM-NEXT: CNDE_INT T0.X, T2.W, PV.W, T0.X, -; CM-NEXT: CNDE_INT T0.Y, T2.Y, T3.X, PV.Z, +; CM-NEXT: CNDE_INT T1.X, T2.X, T0.Y, PV.W, +; CM-NEXT: CNDE_INT T0.Y, T1.Z, PV.Z, T0.X, ; CM-NEXT: LSHL T0.Z, PV.Y, literal.x, -; CM-NEXT: AND_INT * T0.W, KC0[3].Z, literal.y, +; CM-NEXT: AND_INT * T1.W, KC0[3].Z, literal.y, ; CM-NEXT: 23(3.222986e-44), -4096(nan) +; CM-NEXT: MUL_IEEE T0.X, PV.W, literal.x, ; CM-NEXT: ADD T1.Y, KC0[3].Z, -PV.W, -; CM-NEXT: ADD_INT T0.Z, PV.Z, literal.x, -; CM-NEXT: CNDE_INT * T1.W, T3.W, PV.X, PV.Y, -; CM-NEXT: 1065353216(1.000000e+00), 0(0.000000e+00) -; CM-NEXT: MUL_IEEE T0.X, PV.W, PV.Z, -; CM-NEXT: MUL_IEEE T0.Y, PV.Y, literal.x, -; CM-NEXT: MUL_IEEE T0.Z, T0.W, literal.y, -; CM-NEXT: AND_INT * T1.W, KC0[3].W, literal.z, -; CM-NEXT: 975668412(6.390323e-04), 1079283712(3.321289e+00) -; CM-NEXT: -4096(nan), 0(0.000000e+00) -; CM-NEXT: SETGT T1.X, literal.x, KC0[3].Y, -; CM-NEXT: ADD T2.Y, KC0[3].W, -PV.W, -; CM-NEXT: RNDNE T1.Z, PV.Z, -; CM-NEXT: MULADD_IEEE * T2.W, T1.Y, literal.y, PV.Y, -; CM-NEXT: -1036817932(-4.485347e+01), 1079283712(3.321289e+00) -; CM-NEXT: MULADD_IEEE T2.X, T0.W, literal.x, PV.W, -; CM-NEXT: ADD T0.Y, T0.Z, -PV.Z, +; CM-NEXT: ADD_INT T0.Z, PV.Z, literal.y, +; CM-NEXT: CNDE_INT * T0.W, T0.W, PV.Y, PV.X, +; CM-NEXT: 1079283712(3.321289e+00), 1065353216(1.000000e+00) +; CM-NEXT: MUL_IEEE T0.Y, PV.W, PV.Z, ; CM-NEXT: MUL_IEEE T0.Z, PV.Y, literal.x, -; CM-NEXT: MUL_IEEE * T0.W, T1.W, literal.y, BS:VEC_120/SCL_212 -; CM-NEXT: 975668412(6.390323e-04), 1079283712(3.321289e+00) -; CM-NEXT: TRUNC T3.X, T1.Z, -; CM-NEXT: RNDNE T1.Y, PV.W, -; CM-NEXT: MULADD_IEEE T0.Z, T2.Y, literal.x, PV.Z, -; CM-NEXT: ADD * T2.W, PV.Y, PV.X, +; CM-NEXT: RNDNE * T0.W, PV.X, +; CM-NEXT: 975668412(6.390323e-04), 0(0.000000e+00) +; CM-NEXT: SETGT T1.X, literal.x, KC0[3].Y, +; CM-NEXT: TRUNC T2.Y, PV.W, +; CM-NEXT: AND_INT T1.Z, KC0[3].W, literal.y, +; CM-NEXT: MULADD_IEEE * T2.W, T1.Y, literal.z, PV.Z, +; CM-NEXT: -1036817932(-4.485347e+01), -4096(nan) ; CM-NEXT: 1079283712(3.321289e+00), 0(0.000000e+00) -; CM-NEXT: EXP_IEEE T0.X (MASKED), T2.W, -; CM-NEXT: EXP_IEEE T0.Y, T2.W, -; CM-NEXT: EXP_IEEE T0.Z (MASKED), T2.W, -; CM-NEXT: EXP_IEEE * T0.W (MASKED), T2.W, -; CM-NEXT: MULADD_IEEE T2.X, T1.W, literal.x, T0.Z, -; CM-NEXT: ADD T2.Y, T0.W, -T1.Y, BS:VEC_120/SCL_212 -; CM-NEXT: FLT_TO_INT T0.Z, T3.X, -; CM-NEXT: MUL_IEEE * T0.W, PV.Y, literal.y, -; CM-NEXT: 975668412(6.390323e-04), 209715200(1.972152e-31) -; CM-NEXT: MUL_IEEE T3.X, PV.W, literal.x, -; CM-NEXT: SETGT_UINT T3.Y, PV.Z, literal.y, -; CM-NEXT: TRUNC T1.Z, T1.Y, -; CM-NEXT: ADD * T1.W, PV.Y, PV.X, -; CM-NEXT: 209715200(1.972152e-31), -229(nan) +; CM-NEXT: MULADD_IEEE T2.X, T1.W, literal.x, PV.W, +; CM-NEXT: MUL_IEEE T1.Y, PV.Z, literal.y, +; CM-NEXT: FLT_TO_INT T0.Z, PV.Y, +; CM-NEXT: ADD * T1.W, KC0[3].W, -PV.Z, +; CM-NEXT: 975668412(6.390323e-04), 1079283712(3.321289e+00) +; CM-NEXT: ADD T0.X, T0.X, -T0.W, +; CM-NEXT: MUL_IEEE T2.Y, PV.W, literal.x, +; CM-NEXT: MAX_INT T2.Z, PV.Z, literal.y, +; CM-NEXT: RNDNE * T0.W, PV.Y, +; CM-NEXT: 975668412(6.390323e-04), -330(nan) +; CM-NEXT: TRUNC T3.X, PV.W, +; CM-NEXT: ADD_INT T3.Y, PV.Z, literal.x, +; CM-NEXT: MULADD_IEEE T2.Z, T1.W, literal.y, PV.Y, +; CM-NEXT: ADD * T1.W, PV.X, T2.X, +; CM-NEXT: 204(2.858649e-43), 1079283712(3.321289e+00) +; CM-NEXT: EXP_IEEE T0.X, T1.W, +; CM-NEXT: EXP_IEEE T0.Y (MASKED), T1.W, +; CM-NEXT: EXP_IEEE T0.Z (MASKED), T1.W, +; CM-NEXT: EXP_IEEE * T0.W (MASKED), T1.W, +; CM-NEXT: ADD_INT T2.X, T0.Z, literal.x, +; CM-NEXT: MULADD_IEEE T2.Y, T1.Z, literal.y, T2.Z, BS:VEC_102/SCL_221 +; CM-NEXT: ADD T1.Z, T1.Y, -T0.W, +; CM-NEXT: MUL_IEEE * T0.W, PV.X, literal.z, +; CM-NEXT: 102(1.429324e-43), 975668412(6.390323e-04) +; CM-NEXT: 2130706432(1.701412e+38), 0(0.000000e+00) +; CM-NEXT: SETGT_UINT T4.X, T0.Z, literal.x, +; CM-NEXT: MUL_IEEE T1.Y, PV.W, literal.y, +; CM-NEXT: SETGT_UINT T2.Z, T0.Z, literal.z, +; CM-NEXT: ADD * T1.W, PV.Z, PV.Y, +; CM-NEXT: -229(nan), 2130706432(1.701412e+38) +; CM-NEXT: 254(3.559298e-43), 0(0.000000e+00) ; CM-NEXT: EXP_IEEE T1.X (MASKED), T1.W, -; CM-NEXT: EXP_IEEE T1.Y, T1.W, -; CM-NEXT: EXP_IEEE T1.Z (MASKED), T1.W, +; CM-NEXT: EXP_IEEE T1.Y (MASKED), T1.W, +; CM-NEXT: EXP_IEEE T1.Z, T1.W, ; CM-NEXT: EXP_IEEE * T1.W (MASKED), T1.W, -; CM-NEXT: FLT_TO_INT T2.X, T1.Z, -; CM-NEXT: MUL_IEEE T2.Y, PV.Y, literal.x, -; CM-NEXT: CNDE_INT T1.Z, T3.Y, T3.X, T0.W, -; CM-NEXT: SETGT_INT * T0.W, T0.Z, literal.y, BS:VEC_120/SCL_212 -; CM-NEXT: 209715200(1.972152e-31), -127(nan) -; CM-NEXT: CNDE_INT T3.X, PV.W, PV.Z, T0.Y, -; CM-NEXT: MUL_IEEE * T4.Y, PV.Y, literal.x, -; CM-NEXT: 209715200(1.972152e-31), 0(0.000000e+00) -; CM-NEXT: ALU clause starting at 108: -; CM-NEXT: SETGT_UINT T1.Z, T2.X, literal.x, -; CM-NEXT: MAX_INT * T1.W, T0.Z, literal.y, -; CM-NEXT: -229(nan), -330(nan) -; CM-NEXT: ADD_INT T4.X, PV.W, literal.x, -; CM-NEXT: ADD_INT T5.Y, T0.Z, literal.y, -; CM-NEXT: CNDE_INT T2.Z, PV.Z, T4.Y, T2.Y, -; CM-NEXT: SETGT_INT * T1.W, T2.X, literal.z, +; CM-NEXT: ALU clause starting at 109: +; CM-NEXT: CNDE_INT T5.X, T2.Z, T0.W, T1.Y, +; CM-NEXT: CNDE_INT T1.Y, T4.X, T3.Y, T2.X, +; CM-NEXT: FLT_TO_INT T3.Z, T3.X, BS:VEC_120/SCL_212 +; CM-NEXT: MUL_IEEE * T0.W, T1.Z, literal.x, BS:VEC_120/SCL_212 +; CM-NEXT: 2130706432(1.701412e+38), 0(0.000000e+00) +; CM-NEXT: SETGT_INT T2.X, T0.Z, literal.x, +; CM-NEXT: MUL_IEEE T2.Y, T0.X, literal.y, +; CM-NEXT: MUL_IEEE T4.Z, PV.W, literal.z, +; CM-NEXT: SETGT_UINT * T1.W, PV.Z, literal.w, +; CM-NEXT: -127(nan), 209715200(1.972152e-31) +; CM-NEXT: 2130706432(1.701412e+38), 254(3.559298e-43) +; CM-NEXT: CNDE_INT T3.X, PV.W, T0.W, PV.Z, +; CM-NEXT: MUL_IEEE T3.Y, PV.Y, literal.x, +; CM-NEXT: CNDE_INT T4.Z, PV.X, T1.Y, T0.Z, +; CM-NEXT: MAX_INT * T0.W, T3.Z, literal.y, +; CM-NEXT: 209715200(1.972152e-31), -330(nan) +; CM-NEXT: ADD_INT T6.X, PV.W, literal.x, +; CM-NEXT: ADD_INT T1.Y, T3.Z, literal.y, +; CM-NEXT: SETGT_UINT T5.Z, T3.Z, literal.z, +; CM-NEXT: MUL_IEEE * T0.W, T1.Z, literal.w, BS:VEC_120/SCL_212 ; CM-NEXT: 204(2.858649e-43), 102(1.429324e-43) +; CM-NEXT: -229(nan), 209715200(1.972152e-31) +; CM-NEXT: MUL_IEEE T7.X, PV.W, literal.x, +; CM-NEXT: MIN_INT T4.Y, T3.Z, literal.y, +; CM-NEXT: CNDE_INT T6.Z, PV.Z, PV.X, PV.Y, +; CM-NEXT: SETGT_INT * T2.W, T3.Z, literal.z, +; CM-NEXT: 209715200(1.972152e-31), 381(5.338947e-43) ; CM-NEXT: -127(nan), 0(0.000000e+00) -; CM-NEXT: CNDE_INT T5.X, PV.W, PV.Z, T1.Y, -; CM-NEXT: MUL_IEEE T0.Y, T0.Y, literal.x, -; CM-NEXT: MAX_INT T2.Z, T2.X, literal.y, -; CM-NEXT: CNDE_INT * T2.W, T3.Y, PV.X, PV.Y, BS:VEC_120/SCL_212 -; CM-NEXT: 2130706432(1.701412e+38), -330(nan) -; CM-NEXT: CNDE_INT T4.X, T0.W, PV.W, T0.Z, -; CM-NEXT: ADD_INT T2.Y, PV.Z, literal.x, -; CM-NEXT: ADD_INT T2.Z, T2.X, literal.y, -; CM-NEXT: MIN_INT * T0.W, T2.X, literal.z, -; CM-NEXT: 204(2.858649e-43), 102(1.429324e-43) -; CM-NEXT: 381(5.338947e-43), 0(0.000000e+00) -; CM-NEXT: ADD_INT T6.X, PV.W, literal.x, -; CM-NEXT: ADD_INT T3.Y, T2.X, literal.y, -; CM-NEXT: SETGT_UINT T3.Z, T2.X, literal.z, -; CM-NEXT: CNDE_INT * T0.W, T1.Z, PV.Y, PV.Z, -; CM-NEXT: -254(nan), -127(nan) -; CM-NEXT: 254(3.559298e-43), 0(0.000000e+00) -; CM-NEXT: MUL_IEEE T7.X, T1.Y, literal.x, -; CM-NEXT: CNDE_INT T1.Y, T1.W, PV.W, T2.X, -; CM-NEXT: CNDE_INT T1.Z, PV.Z, PV.Y, PV.X, -; CM-NEXT: MIN_INT * T0.W, T0.Z, literal.y, -; CM-NEXT: 2130706432(1.701412e+38), 381(5.338947e-43) -; CM-NEXT: SETGT_INT T2.X, T2.X, literal.x, -; CM-NEXT: ADD_INT T2.Y, PV.W, literal.y, -; CM-NEXT: ADD_INT T2.Z, T0.Z, literal.z, -; CM-NEXT: SETGT_UINT * T0.W, T0.Z, literal.w, +; CM-NEXT: CNDE_INT T6.X, PV.W, PV.Z, T3.Z, +; CM-NEXT: MIN_INT T1.Y, T0.Z, literal.x, +; CM-NEXT: ADD_INT T6.Z, PV.Y, literal.y, +; CM-NEXT: ADD_INT * T3.W, T3.Z, literal.z, BS:VEC_120/SCL_212 +; CM-NEXT: 381(5.338947e-43), -254(nan) +; CM-NEXT: -127(nan), 0(0.000000e+00) +; CM-NEXT: CNDE_INT T8.X, T1.W, PV.W, PV.Z, +; CM-NEXT: SETGT_INT T4.Y, T3.Z, literal.x, +; CM-NEXT: ADD_INT T3.Z, PV.Y, literal.y, +; CM-NEXT: ADD_INT * T1.W, T0.Z, literal.z, BS:VEC_120/SCL_212 ; CM-NEXT: 127(1.779649e-43), -254(nan) -; CM-NEXT: -127(nan), 254(3.559298e-43) -; CM-NEXT: CNDE_INT T6.X, PV.W, PV.Z, PV.Y, -; CM-NEXT: SETGT_INT T2.Y, T0.Z, literal.x, -; CM-NEXT: CNDE_INT T0.Z, PV.X, T1.Y, T1.Z, -; CM-NEXT: MUL_IEEE * T1.W, T7.X, literal.y, -; CM-NEXT: 127(1.779649e-43), 2130706432(1.701412e+38) -; CM-NEXT: CNDE_INT T7.X, T3.Z, T7.X, PV.W, -; CM-NEXT: LSHL T1.Y, PV.Z, literal.x, -; CM-NEXT: CNDE_INT T0.Z, PV.Y, T4.X, PV.X, BS:VEC_021/SCL_122 -; CM-NEXT: MUL_IEEE * T1.W, T0.Y, literal.y, -; CM-NEXT: 23(3.222986e-44), 2130706432(1.701412e+38) -; CM-NEXT: CNDE_INT T4.X, T0.W, T0.Y, PV.W, -; CM-NEXT: LSHL T0.Y, PV.Z, literal.x, +; CM-NEXT: -127(nan), 0(0.000000e+00) +; CM-NEXT: CNDE_INT T9.X, T2.Z, PV.W, PV.Z, +; CM-NEXT: SETGT_INT T1.Y, T0.Z, literal.x, BS:VEC_120/SCL_212 +; CM-NEXT: CNDE_INT T0.Z, PV.Y, T6.X, PV.X, +; CM-NEXT: CNDE_INT * T0.W, T5.Z, T7.X, T0.W, BS:VEC_201 +; CM-NEXT: 127(1.779649e-43), 0(0.000000e+00) +; CM-NEXT: CNDE_INT T6.X, T2.W, PV.W, T1.Z, +; CM-NEXT: LSHL T5.Y, PV.Z, literal.x, +; CM-NEXT: CNDE_INT T0.Z, PV.Y, T4.Z, PV.X, +; CM-NEXT: CNDE_INT * T0.W, T4.X, T3.Y, T2.Y, +; CM-NEXT: 23(3.222986e-44), 0(0.000000e+00) +; CM-NEXT: CNDE_INT T0.X, T2.X, PV.W, T0.X, +; CM-NEXT: LSHL T2.Y, PV.Z, literal.x, ; CM-NEXT: ADD_INT T0.Z, PV.Y, literal.y, -; CM-NEXT: CNDE_INT * T0.W, T2.X, T5.X, PV.X, +; CM-NEXT: CNDE_INT * T0.W, T4.Y, PV.X, T3.X, BS:VEC_021/SCL_122 ; CM-NEXT: 23(3.222986e-44), 1065353216(1.000000e+00) ; CM-NEXT: MUL_IEEE T2.X, PV.W, PV.Z, -; CM-NEXT: SETGT T1.Y, literal.x, KC0[3].W, +; CM-NEXT: SETGT T3.Y, literal.x, KC0[3].W, ; CM-NEXT: ADD_INT T0.Z, PV.Y, literal.y, -; CM-NEXT: CNDE_INT * T0.W, T2.Y, T3.X, PV.X, +; CM-NEXT: CNDE_INT * T0.W, T1.Y, PV.X, T5.X, ; CM-NEXT: -1036817932(-4.485347e+01), 1065353216(1.000000e+00) -; CM-NEXT: MUL_IEEE T3.X, PV.W, PV.Z, -; CM-NEXT: SETGT T0.Y, literal.x, KC0[3].Z, +; CM-NEXT: MUL_IEEE T0.X, PV.W, PV.Z, +; CM-NEXT: SETGT T1.Y, literal.x, KC0[3].Z, ; CM-NEXT: CNDE T0.Z, PV.Y, PV.X, 0.0, ; CM-NEXT: SETGT * T0.W, KC0[3].W, literal.y, ; CM-NEXT: -1036817932(-4.485347e+01), 1109008539(3.853184e+01) ; CM-NEXT: CNDE T2.X, PV.W, PV.Z, literal.x, -; CM-NEXT: CNDE T0.Y, PV.Y, PV.X, 0.0, +; CM-NEXT: CNDE T1.Y, PV.Y, PV.X, 0.0, ; CM-NEXT: SETGT T0.Z, KC0[3].Z, literal.y, ; CM-NEXT: ADD_INT * T0.W, KC0[2].Y, literal.z, ; CM-NEXT: 2139095040(INF), 1109008539(3.853184e+01) ; CM-NEXT: 8(1.121039e-44), 0(0.000000e+00) -; CM-NEXT: LSHR T3.X, PV.W, literal.x, -; CM-NEXT: CNDE T0.Y, PV.Z, PV.Y, literal.y, -; CM-NEXT: CNDE T0.Z, T1.X, T0.X, 0.0, +; CM-NEXT: LSHR T0.X, PV.W, literal.x, +; CM-NEXT: CNDE T1.Y, PV.Z, PV.Y, literal.y, +; CM-NEXT: CNDE T0.Z, T1.X, T0.Y, 0.0, ; CM-NEXT: SETGT * T0.W, KC0[3].Y, literal.z, ; CM-NEXT: 2(2.802597e-45), 2139095040(INF) ; CM-NEXT: 1109008539(3.853184e+01), 0(0.000000e+00) -; CM-NEXT: CNDE * T0.X, PV.W, PV.Z, literal.x, +; CM-NEXT: CNDE * T1.X, PV.W, PV.Z, literal.x, ; CM-NEXT: 2139095040(INF), 0(0.000000e+00) -; CM-NEXT: LSHR * T1.X, KC0[2].Y, literal.x, +; CM-NEXT: LSHR * T3.X, KC0[2].Y, literal.x, ; CM-NEXT: 2(2.802597e-45), 0(0.000000e+00) %result = call <3 x float> @llvm.exp10.v3f32(<3 x float> %in) store <3 x float> %result, ptr addrspace(1) %out @@ -2043,224 +2052,227 @@ define amdgpu_kernel void @s_exp10_v4f32(ptr addrspace(1) %out, <4 x float> %in) ; R600-LABEL: s_exp10_v4f32: ; R600: ; %bb.0: ; R600-NEXT: ALU 98, @6, KC0[CB0:0-32], KC1[] -; R600-NEXT: ALU 95, @105, KC0[CB0:0-32], KC1[] -; R600-NEXT: ALU 24, @201, KC0[CB0:0-32], KC1[] +; R600-NEXT: ALU 98, @105, KC0[CB0:0-32], KC1[] +; R600-NEXT: ALU 24, @204, KC0[CB0:0-32], KC1[] ; R600-NEXT: MEM_RAT_CACHELESS STORE_RAW T1.XYZW, T0.X, 1 ; R600-NEXT: CF_END ; R600-NEXT: PAD ; R600-NEXT: ALU clause starting at 6: ; R600-NEXT: AND_INT * T0.W, KC0[3].Z, literal.x, ; R600-NEXT: -4096(nan), 0(0.000000e+00) -; R600-NEXT: ADD * T1.W, KC0[3].Z, -PV.W, -; R600-NEXT: MUL_IEEE T2.W, PV.W, literal.x, -; R600-NEXT: MUL_IEEE * T3.W, T0.W, literal.y, -; R600-NEXT: 975668412(6.390323e-04), 1079283712(3.321289e+00) -; R600-NEXT: RNDNE T4.W, PS, -; R600-NEXT: MULADD_IEEE * T1.W, T1.W, literal.x, PV.W, BS:VEC_021/SCL_122 +; R600-NEXT: ADD T1.W, KC0[3].Z, -PV.W, +; R600-NEXT: MUL_IEEE * T2.W, PV.W, literal.x, ; R600-NEXT: 1079283712(3.321289e+00), 0(0.000000e+00) -; R600-NEXT: MULADD_IEEE T0.W, T0.W, literal.x, PS, -; R600-NEXT: ADD * T1.W, T3.W, -PV.W, +; R600-NEXT: RNDNE T3.W, PS, +; R600-NEXT: MUL_IEEE * T4.W, PV.W, literal.x, ; R600-NEXT: 975668412(6.390323e-04), 0(0.000000e+00) -; R600-NEXT: ADD T0.W, PS, PV.W, -; R600-NEXT: TRUNC * T1.W, T4.W, -; R600-NEXT: FLT_TO_INT T1.W, PS, -; R600-NEXT: EXP_IEEE * T0.X, PV.W, -; R600-NEXT: MUL_IEEE T0.Z, PS, literal.x, -; R600-NEXT: MAX_INT T0.W, PV.W, literal.y, -; R600-NEXT: MIN_INT * T2.W, PV.W, literal.z, -; R600-NEXT: 209715200(1.972152e-31), -330(nan) +; R600-NEXT: MULADD_IEEE T1.W, T1.W, literal.x, PS, +; R600-NEXT: TRUNC * T4.W, PV.W, +; R600-NEXT: 1079283712(3.321289e+00), 0(0.000000e+00) +; R600-NEXT: FLT_TO_INT T0.Z, PS, +; R600-NEXT: MULADD_IEEE T0.W, T0.W, literal.x, PV.W, +; R600-NEXT: ADD * T1.W, T2.W, -T3.W, +; R600-NEXT: 975668412(6.390323e-04), 0(0.000000e+00) +; R600-NEXT: ADD T1.Z, PS, PV.W, +; R600-NEXT: MAX_INT T0.W, PV.Z, literal.x, +; R600-NEXT: MIN_INT * T1.W, PV.Z, literal.y, +; R600-NEXT: -330(nan), 381(5.338947e-43) +; R600-NEXT: ADD_INT T0.X, PS, literal.x, +; R600-NEXT: ADD_INT T0.Y, PV.W, literal.y, +; R600-NEXT: ADD_INT T2.Z, T0.Z, literal.z, +; R600-NEXT: SETGT_UINT T0.W, T0.Z, literal.w, +; R600-NEXT: EXP_IEEE * T1.X, PV.Z, +; R600-NEXT: -254(nan), 204(2.858649e-43) +; R600-NEXT: 102(1.429324e-43), -229(nan) +; R600-NEXT: ADD_INT T2.X, T0.Z, literal.x, +; R600-NEXT: SETGT_UINT T1.Y, T0.Z, literal.y, +; R600-NEXT: CNDE_INT T1.Z, PV.W, PV.Y, PV.Z, +; R600-NEXT: SETGT_INT T1.W, T0.Z, literal.x, +; R600-NEXT: MUL_IEEE * T2.W, PS, literal.z, +; R600-NEXT: -127(nan), 254(3.559298e-43) +; R600-NEXT: 209715200(1.972152e-31), 0(0.000000e+00) +; R600-NEXT: MUL_IEEE T3.X, T1.X, literal.x, +; R600-NEXT: MUL_IEEE T0.Y, PS, literal.y, +; R600-NEXT: CNDE_INT T1.Z, PV.W, PV.Z, T0.Z, +; R600-NEXT: CNDE_INT T3.W, PV.Y, PV.X, T0.X, +; R600-NEXT: SETGT_INT * T4.W, T0.Z, literal.z, +; R600-NEXT: 2130706432(1.701412e+38), 209715200(1.972152e-31) +; R600-NEXT: 127(1.779649e-43), 0(0.000000e+00) +; R600-NEXT: AND_INT T2.Y, KC0[4].X, literal.x, +; R600-NEXT: CNDE_INT T0.Z, PS, PV.Z, PV.W, +; R600-NEXT: CNDE_INT T0.W, T0.W, PV.Y, T2.W, +; R600-NEXT: MUL_IEEE * T2.W, PV.X, literal.y, +; R600-NEXT: -4096(nan), 2130706432(1.701412e+38) +; R600-NEXT: CNDE_INT T0.X, T1.Y, T3.X, PS, +; R600-NEXT: CNDE_INT T0.Y, T1.W, PV.W, T1.X, +; R600-NEXT: LSHL T0.Z, PV.Z, literal.x, +; R600-NEXT: ADD T0.W, KC0[4].X, -PV.Y, +; R600-NEXT: MUL_IEEE * T1.W, PV.Y, literal.y, +; R600-NEXT: 23(3.222986e-44), 1079283712(3.321289e+00) +; R600-NEXT: RNDNE T1.Y, PS, +; R600-NEXT: MUL_IEEE T1.Z, PV.W, literal.x, +; R600-NEXT: ADD_INT T2.W, PV.Z, literal.y, +; R600-NEXT: CNDE_INT * T3.W, T4.W, PV.Y, PV.X, +; R600-NEXT: 975668412(6.390323e-04), 1065353216(1.000000e+00) +; R600-NEXT: MUL_IEEE T0.Y, PS, PV.W, +; R600-NEXT: AND_INT T0.Z, KC0[3].W, literal.x, +; R600-NEXT: MULADD_IEEE T0.W, T0.W, literal.y, PV.Z, +; R600-NEXT: TRUNC * T2.W, PV.Y, +; R600-NEXT: -4096(nan), 1079283712(3.321289e+00) +; R600-NEXT: SETGT T0.X, literal.x, KC0[3].Z, +; R600-NEXT: FLT_TO_INT T3.Y, PS, +; R600-NEXT: MULADD_IEEE T1.Z, T2.Y, literal.y, PV.W, +; R600-NEXT: ADD T0.W, T1.W, -T1.Y, +; R600-NEXT: MUL_IEEE * T1.W, PV.Z, literal.z, +; R600-NEXT: -1036817932(-4.485347e+01), 975668412(6.390323e-04) +; R600-NEXT: 1079283712(3.321289e+00), 0(0.000000e+00) +; R600-NEXT: RNDNE T1.X, PS, +; R600-NEXT: AND_INT T1.Y, KC0[3].Y, literal.x, +; R600-NEXT: ADD T1.Z, PV.W, PV.Z, +; R600-NEXT: MAX_INT T0.W, PV.Y, literal.y, +; R600-NEXT: MIN_INT * T2.W, PV.Y, literal.z, +; R600-NEXT: -4096(nan), -330(nan) ; R600-NEXT: 381(5.338947e-43), 0(0.000000e+00) -; R600-NEXT: ADD_INT T1.X, PS, literal.x, -; R600-NEXT: AND_INT T0.Y, KC0[4].X, literal.y, -; R600-NEXT: ADD_INT T1.Z, PV.W, literal.z, -; R600-NEXT: ADD_INT * T0.W, T1.W, literal.w, -; R600-NEXT: -254(nan), -4096(nan) -; R600-NEXT: 204(2.858649e-43), 102(1.429324e-43) -; R600-NEXT: SETGT_UINT * T2.W, T1.W, literal.x, -; R600-NEXT: -229(nan), 0(0.000000e+00) -; R600-NEXT: ADD_INT T2.X, T1.W, literal.x, -; R600-NEXT: SETGT_UINT T1.Y, T1.W, literal.y, -; R600-NEXT: CNDE_INT T1.Z, PV.W, T1.Z, T0.W, -; R600-NEXT: SETGT_INT T0.W, T1.W, literal.x, -; R600-NEXT: ADD * T3.W, KC0[4].X, -T0.Y, +; R600-NEXT: ADD_INT T2.X, PS, literal.x, +; R600-NEXT: ADD_INT T2.Y, PV.W, literal.y, +; R600-NEXT: ADD_INT T2.Z, T3.Y, literal.z, +; R600-NEXT: SETGT_UINT T0.W, T3.Y, literal.w, +; R600-NEXT: EXP_IEEE * T1.Z, PV.Z, +; R600-NEXT: -254(nan), 204(2.858649e-43) +; R600-NEXT: 102(1.429324e-43), -229(nan) +; R600-NEXT: ADD_INT T3.X, T3.Y, literal.x, +; R600-NEXT: SETGT_UINT T4.Y, T3.Y, literal.y, +; R600-NEXT: CNDE_INT T2.Z, PV.W, PV.Y, PV.Z, +; R600-NEXT: SETGT_INT T2.W, T3.Y, literal.x, +; R600-NEXT: MUL_IEEE * T3.W, PS, literal.z, ; R600-NEXT: -127(nan), 254(3.559298e-43) -; R600-NEXT: MUL_IEEE T3.X, PS, literal.x, -; R600-NEXT: MUL_IEEE T2.Y, T0.Y, literal.y, -; R600-NEXT: CNDE_INT T1.Z, PV.W, PV.Z, T1.W, -; R600-NEXT: CNDE_INT T4.W, PV.Y, PV.X, T1.X, -; R600-NEXT: SETGT_INT * T1.W, T1.W, literal.z, -; R600-NEXT: 975668412(6.390323e-04), 1079283712(3.321289e+00) +; R600-NEXT: 209715200(1.972152e-31), 0(0.000000e+00) +; R600-NEXT: MUL_IEEE T4.X, T1.Z, literal.x, +; R600-NEXT: MUL_IEEE T2.Y, PS, literal.y, +; R600-NEXT: CNDE_INT T2.Z, PV.W, PV.Z, T3.Y, +; R600-NEXT: CNDE_INT T4.W, PV.Y, PV.X, T2.X, +; R600-NEXT: SETGT_INT * T5.W, T3.Y, literal.z, +; R600-NEXT: 2130706432(1.701412e+38), 209715200(1.972152e-31) ; R600-NEXT: 127(1.779649e-43), 0(0.000000e+00) -; R600-NEXT: CNDE_INT T1.X, PS, PV.Z, PV.W, -; R600-NEXT: RNDNE T3.Y, PV.Y, -; R600-NEXT: MULADD_IEEE T1.Z, T3.W, literal.x, PV.X, -; R600-NEXT: MUL_IEEE T3.W, T0.Z, literal.y, -; R600-NEXT: MUL_IEEE * T4.W, T0.X, literal.z, -; R600-NEXT: 1079283712(3.321289e+00), 209715200(1.972152e-31) +; R600-NEXT: ADD T2.X, KC0[3].W, -T0.Z, +; R600-NEXT: CNDE_INT T3.Y, PS, PV.Z, PV.W, +; R600-NEXT: CNDE_INT * T2.Z, T0.W, PV.Y, T3.W, +; R600-NEXT: ALU clause starting at 105: +; R600-NEXT: MUL_IEEE T0.W, T4.X, literal.x, +; R600-NEXT: ADD * T3.W, KC0[3].Y, -T1.Y, ; R600-NEXT: 2130706432(1.701412e+38), 0(0.000000e+00) -; R600-NEXT: MUL_IEEE T2.X, PS, literal.x, -; R600-NEXT: CNDE_INT T4.Y, T2.W, PV.W, T0.Z, -; R600-NEXT: MULADD_IEEE T0.Z, T0.Y, literal.y, PV.Z, -; R600-NEXT: ADD T2.W, T2.Y, -PV.Y, BS:VEC_120/SCL_212 -; R600-NEXT: AND_INT * T3.W, KC0[3].Y, literal.z, -; R600-NEXT: 2130706432(1.701412e+38), 975668412(6.390323e-04) -; R600-NEXT: -4096(nan), 0(0.000000e+00) ; R600-NEXT: MUL_IEEE T3.X, PS, literal.x, -; R600-NEXT: ADD T0.Y, PV.W, PV.Z, -; R600-NEXT: CNDE_INT T0.Z, T0.W, PV.Y, T0.X, BS:VEC_021/SCL_122 -; R600-NEXT: CNDE_INT T0.W, T1.Y, T4.W, PV.X, -; R600-NEXT: LSHL * T2.W, T1.X, literal.y, -; R600-NEXT: 1079283712(3.321289e+00), 23(3.222986e-44) -; R600-NEXT: AND_INT T0.X, KC0[3].W, literal.x, -; R600-NEXT: TRUNC T1.Y, T3.Y, -; R600-NEXT: ADD_INT T1.Z, PS, literal.y, -; R600-NEXT: CNDE_INT T0.W, T1.W, PV.Z, PV.W, -; R600-NEXT: EXP_IEEE * T0.Y, PV.Y, -; R600-NEXT: -4096(nan), 1065353216(1.000000e+00) -; R600-NEXT: MUL_IEEE T1.X, PV.W, PV.Z, -; R600-NEXT: FLT_TO_INT T1.Y, PV.Y, -; R600-NEXT: MUL_IEEE T0.Z, PS, literal.x, -; R600-NEXT: ADD T0.W, KC0[3].W, -PV.X, -; R600-NEXT: RNDNE * T1.W, T3.X, -; R600-NEXT: 209715200(1.972152e-31), 0(0.000000e+00) -; R600-NEXT: SETGT T2.X, literal.x, KC0[3].Z, -; R600-NEXT: TRUNC T2.Y, PS, -; R600-NEXT: MUL_IEEE T1.Z, PV.W, literal.y, -; R600-NEXT: MUL_IEEE T2.W, PV.Z, literal.z, -; R600-NEXT: MAX_INT * T4.W, PV.Y, literal.w, -; R600-NEXT: -1036817932(-4.485347e+01), 975668412(6.390323e-04) -; R600-NEXT: 209715200(1.972152e-31), -330(nan) -; R600-NEXT: ADD T4.X, KC0[3].Y, -T3.W, -; R600-NEXT: ADD_INT T3.Y, PS, literal.x, -; R600-NEXT: ADD_INT T2.Z, T1.Y, literal.y, -; R600-NEXT: SETGT_UINT T4.W, T1.Y, literal.z, -; R600-NEXT: MIN_INT * T5.W, T1.Y, literal.w, -; R600-NEXT: 204(2.858649e-43), 102(1.429324e-43) -; R600-NEXT: -229(nan), 381(5.338947e-43) -; R600-NEXT: ADD_INT T5.X, PS, literal.x, -; R600-NEXT: ADD_INT T4.Y, T1.Y, literal.y, -; R600-NEXT: SETGT_UINT T3.Z, T1.Y, literal.z, -; R600-NEXT: CNDE_INT T5.W, PV.W, PV.Y, PV.Z, -; R600-NEXT: SETGT_INT * T6.W, T1.Y, literal.y, -; R600-NEXT: -254(nan), -127(nan) -; R600-NEXT: 254(3.559298e-43), 0(0.000000e+00) -; R600-NEXT: MUL_IEEE T6.X, T0.Y, literal.x, -; R600-NEXT: CNDE_INT T3.Y, PS, PV.W, T1.Y, -; R600-NEXT: CNDE_INT * T2.Z, PV.Z, PV.Y, PV.X, -; R600-NEXT: 2130706432(1.701412e+38), 0(0.000000e+00) -; R600-NEXT: ALU clause starting at 105: -; R600-NEXT: SETGT_INT T5.W, T1.Y, literal.x, -; R600-NEXT: MUL_IEEE * T7.W, T4.X, literal.y, -; R600-NEXT: 127(1.779649e-43), 975668412(6.390323e-04) -; R600-NEXT: MUL_IEEE T5.X, T0.X, literal.x, -; R600-NEXT: MULADD_IEEE T1.Y, T4.X, literal.x, PS, BS:VEC_120/SCL_212 -; R600-NEXT: CNDE_INT T2.Z, PV.W, T3.Y, T2.Z, -; R600-NEXT: MUL_IEEE T7.W, T6.X, literal.y, BS:VEC_201 -; R600-NEXT: CNDE_INT * T2.W, T4.W, T2.W, T0.Z, -; R600-NEXT: 1079283712(3.321289e+00), 2130706432(1.701412e+38) -; R600-NEXT: CNDE_INT T4.X, T6.W, PS, T0.Y, -; R600-NEXT: CNDE_INT T0.Y, T3.Z, T6.X, PV.W, -; R600-NEXT: LSHL T0.Z, PV.Z, literal.x, -; R600-NEXT: MULADD_IEEE T2.W, T3.W, literal.y, PV.Y, BS:VEC_201 -; R600-NEXT: ADD * T1.W, T3.X, -T1.W, -; R600-NEXT: 23(3.222986e-44), 975668412(6.390323e-04) -; R600-NEXT: ADD T3.X, PS, PV.W, -; R600-NEXT: ADD_INT T1.Y, PV.Z, literal.x, -; R600-NEXT: CNDE_INT T0.Z, T5.W, PV.X, PV.Y, -; R600-NEXT: RNDNE T1.W, T5.X, -; R600-NEXT: MULADD_IEEE * T0.W, T0.W, literal.y, T1.Z, BS:VEC_021/SCL_122 +; R600-NEXT: MUL_IEEE T2.Y, T1.Y, literal.y, +; R600-NEXT: CNDE_INT T3.Z, T4.Y, T4.X, PV.W, BS:VEC_120/SCL_212 +; R600-NEXT: CNDE_INT T0.W, T2.W, T2.Z, T1.Z, +; R600-NEXT: LSHL * T2.W, T3.Y, literal.z, +; R600-NEXT: 975668412(6.390323e-04), 1079283712(3.321289e+00) +; R600-NEXT: 23(3.222986e-44), 0(0.000000e+00) +; R600-NEXT: ADD_INT T4.X, PS, literal.x, +; R600-NEXT: CNDE_INT T3.Y, T5.W, PV.W, PV.Z, +; R600-NEXT: RNDNE T1.Z, PV.Y, +; R600-NEXT: MULADD_IEEE T0.W, T3.W, literal.y, PV.X, BS:VEC_120/SCL_212 +; R600-NEXT: MUL_IEEE * T2.W, T2.X, literal.z, ; R600-NEXT: 1065353216(1.000000e+00), 1079283712(3.321289e+00) -; R600-NEXT: MULADD_IEEE T0.X, T0.X, literal.x, PS, -; R600-NEXT: ADD T0.Y, T5.X, -PV.W, BS:VEC_120/SCL_212 -; R600-NEXT: MUL_IEEE T0.Z, PV.Z, PV.Y, -; R600-NEXT: SETGT T0.W, literal.y, KC0[4].X, -; R600-NEXT: EXP_IEEE * T1.Y, PV.X, -; R600-NEXT: 975668412(6.390323e-04), -1036817932(-4.485347e+01) -; R600-NEXT: CNDE T3.X, PV.W, PV.Z, 0.0, -; R600-NEXT: ADD T0.Y, PV.Y, PV.X, -; R600-NEXT: FLT_TO_INT T0.Z, T2.Y, -; R600-NEXT: TRUNC T0.W, T1.W, -; R600-NEXT: MUL_IEEE * T1.W, PS, literal.x, +; R600-NEXT: 975668412(6.390323e-04), 0(0.000000e+00) +; R600-NEXT: MULADD_IEEE T2.X, T2.X, literal.x, PS, +; R600-NEXT: MULADD_IEEE T1.Y, T1.Y, literal.y, PV.W, +; R600-NEXT: ADD T2.Z, T2.Y, -PV.Z, BS:VEC_120/SCL_212 +; R600-NEXT: MUL_IEEE T0.W, PV.Y, PV.X, +; R600-NEXT: SETGT * T2.W, literal.z, KC0[4].X, +; R600-NEXT: 1079283712(3.321289e+00), 975668412(6.390323e-04) +; R600-NEXT: -1036817932(-4.485347e+01), 0(0.000000e+00) +; R600-NEXT: CNDE T3.X, PS, PV.W, 0.0, +; R600-NEXT: ADD T1.Y, PV.Z, PV.Y, +; R600-NEXT: TRUNC T1.Z, T1.Z, +; R600-NEXT: MULADD_IEEE T0.W, T0.Z, literal.x, PV.X, BS:VEC_120/SCL_212 +; R600-NEXT: ADD * T1.W, T1.W, -T1.X, +; R600-NEXT: 975668412(6.390323e-04), 0(0.000000e+00) +; R600-NEXT: SETGT T2.X, KC0[4].X, literal.x, +; R600-NEXT: ADD T2.Y, PS, PV.W, +; R600-NEXT: FLT_TO_INT T0.Z, PV.Z, +; R600-NEXT: TRUNC T0.W, T1.X, +; R600-NEXT: EXP_IEEE * T1.X, PV.Y, +; R600-NEXT: 1109008539(3.853184e+01), 0(0.000000e+00) +; R600-NEXT: MUL_IEEE T4.X, PS, literal.x, +; R600-NEXT: FLT_TO_INT T1.Y, PV.W, +; R600-NEXT: MAX_INT T1.Z, PV.Z, literal.y, +; R600-NEXT: MUL_IEEE T0.W, PS, literal.z, +; R600-NEXT: EXP_IEEE * T1.W, PV.Y, +; R600-NEXT: 2130706432(1.701412e+38), -330(nan) ; R600-NEXT: 209715200(1.972152e-31), 0(0.000000e+00) -; R600-NEXT: SETGT T0.X, KC0[4].X, literal.x, -; R600-NEXT: MUL_IEEE T2.Y, PS, literal.y, -; R600-NEXT: FLT_TO_INT T1.Z, PV.W, -; R600-NEXT: MAX_INT T0.W, PV.Z, literal.z, -; R600-NEXT: EXP_IEEE * T0.Y, PV.Y, -; R600-NEXT: 1109008539(3.853184e+01), 209715200(1.972152e-31) -; R600-NEXT: -330(nan), 0(0.000000e+00) -; R600-NEXT: MUL_IEEE T4.X, T1.Y, literal.x, -; R600-NEXT: MUL_IEEE T3.Y, PS, literal.y, -; R600-NEXT: ADD_INT T2.Z, PV.W, literal.z, -; R600-NEXT: ADD_INT * T0.W, T0.Z, literal.w, -; R600-NEXT: 2130706432(1.701412e+38), 209715200(1.972152e-31) -; R600-NEXT: 204(2.858649e-43), 102(1.429324e-43) -; R600-NEXT: MAX_INT * T2.W, T1.Z, literal.x, -; R600-NEXT: -330(nan), 0(0.000000e+00) -; R600-NEXT: SETGT_UINT T5.X, T0.Z, literal.x, -; R600-NEXT: ADD_INT T4.Y, PV.W, literal.y, -; R600-NEXT: ADD_INT T3.Z, T1.Z, literal.z, BS:VEC_120/SCL_212 -; R600-NEXT: SETGT_UINT T2.W, T1.Z, literal.x, BS:VEC_120/SCL_212 -; R600-NEXT: MIN_INT * T3.W, T1.Z, literal.w, +; R600-NEXT: MUL_IEEE T5.X, PV.W, literal.x, +; R600-NEXT: MUL_IEEE T2.Y, PS, literal.x, +; R600-NEXT: ADD_INT T1.Z, PV.Z, literal.y, +; R600-NEXT: ADD_INT T2.W, T0.Z, literal.z, +; R600-NEXT: MAX_INT * T3.W, PV.Y, literal.w, +; R600-NEXT: 209715200(1.972152e-31), 204(2.858649e-43) +; R600-NEXT: 102(1.429324e-43), -330(nan) +; R600-NEXT: SETGT_UINT T6.X, T0.Z, literal.x, +; R600-NEXT: ADD_INT T3.Y, PS, literal.y, +; R600-NEXT: ADD_INT T2.Z, T1.Y, literal.z, +; R600-NEXT: SETGT_UINT T3.W, T1.Y, literal.x, +; R600-NEXT: MIN_INT * T4.W, T1.Y, literal.w, ; R600-NEXT: -229(nan), 204(2.858649e-43) ; R600-NEXT: 102(1.429324e-43), 381(5.338947e-43) -; R600-NEXT: ADD_INT T6.X, PS, literal.x, -; R600-NEXT: ADD_INT T5.Y, T1.Z, literal.y, -; R600-NEXT: SETGT_UINT T4.Z, T1.Z, literal.z, -; R600-NEXT: CNDE_INT T3.W, PV.W, PV.Y, PV.Z, -; R600-NEXT: SETGT_INT * T4.W, T1.Z, literal.y, +; R600-NEXT: ADD_INT T7.X, PS, literal.x, +; R600-NEXT: ADD_INT T4.Y, T1.Y, literal.y, +; R600-NEXT: SETGT_UINT T3.Z, T1.Y, literal.z, +; R600-NEXT: CNDE_INT T4.W, PV.W, PV.Y, PV.Z, +; R600-NEXT: SETGT_INT * T5.W, T1.Y, literal.y, ; R600-NEXT: -254(nan), -127(nan) ; R600-NEXT: 254(3.559298e-43), 0(0.000000e+00) -; R600-NEXT: CNDE_INT T7.X, PS, PV.W, T1.Z, BS:VEC_021/SCL_122 -; R600-NEXT: CNDE_INT T4.Y, PV.Z, PV.Y, PV.X, -; R600-NEXT: SETGT_INT T1.Z, T1.Z, literal.x, BS:VEC_120/SCL_212 -; R600-NEXT: CNDE_INT T0.W, T5.X, T2.Z, T0.W, BS:VEC_102/SCL_221 -; R600-NEXT: SETGT_INT * T3.W, T0.Z, literal.y, +; R600-NEXT: CNDE_INT T8.X, PS, PV.W, T1.Y, +; R600-NEXT: CNDE_INT T3.Y, PV.Z, PV.Y, PV.X, +; R600-NEXT: SETGT_INT T2.Z, T1.Y, literal.x, +; R600-NEXT: CNDE_INT T2.W, T6.X, T1.Z, T2.W, +; R600-NEXT: SETGT_INT * T4.W, T0.Z, literal.y, ; R600-NEXT: 127(1.779649e-43), -127(nan) -; R600-NEXT: CNDE_INT T6.X, PS, PV.W, T0.Z, -; R600-NEXT: CNDE_INT T4.Y, PV.Z, PV.X, PV.Y, -; R600-NEXT: MIN_INT T2.Z, T0.Z, literal.x, -; R600-NEXT: MUL_IEEE T0.W, T3.Y, literal.y, -; R600-NEXT: MUL_IEEE * T5.W, T0.Y, literal.z, -; R600-NEXT: 381(5.338947e-43), 209715200(1.972152e-31) -; R600-NEXT: 2130706432(1.701412e+38), 0(0.000000e+00) -; R600-NEXT: MUL_IEEE T7.X, PS, literal.x, -; R600-NEXT: CNDE_INT T3.Y, T2.W, PV.W, T3.Y, -; R600-NEXT: ADD_INT T2.Z, PV.Z, literal.y, -; R600-NEXT: ADD_INT T0.W, T0.Z, literal.z, -; R600-NEXT: SETGT_UINT * T2.W, T0.Z, literal.w, +; R600-NEXT: CNDE_INT T7.X, PS, PV.W, T0.Z, +; R600-NEXT: CNDE_INT T1.Y, PV.Z, PV.X, PV.Y, +; R600-NEXT: MIN_INT T1.Z, T0.Z, literal.x, +; R600-NEXT: MUL_IEEE T2.W, T1.W, literal.y, +; R600-NEXT: MUL_IEEE * T6.W, T2.Y, literal.z, +; R600-NEXT: 381(5.338947e-43), 2130706432(1.701412e+38) +; R600-NEXT: 209715200(1.972152e-31), 0(0.000000e+00) +; R600-NEXT: CNDE_INT T8.X, T3.W, PS, T2.Y, +; R600-NEXT: MUL_IEEE T2.Y, PV.W, literal.x, +; R600-NEXT: ADD_INT T1.Z, PV.Z, literal.y, +; R600-NEXT: ADD_INT T3.W, T0.Z, literal.z, +; R600-NEXT: SETGT_UINT * T6.W, T0.Z, literal.w, ; R600-NEXT: 2130706432(1.701412e+38), -254(nan) ; R600-NEXT: -127(nan), 254(3.559298e-43) -; R600-NEXT: CNDE_INT T8.X, PS, PV.W, PV.Z, -; R600-NEXT: SETGT_INT T5.Y, T0.Z, literal.x, -; R600-NEXT: CNDE_INT T0.Z, T4.W, PV.Y, T0.Y, BS:VEC_021/SCL_122 -; R600-NEXT: CNDE_INT T0.W, T4.Z, T5.W, PV.X, BS:VEC_120/SCL_212 -; R600-NEXT: LSHL * T4.W, T4.Y, literal.y, +; R600-NEXT: CNDE_INT T9.X, PS, PV.W, PV.Z, +; R600-NEXT: SETGT_INT T3.Y, T0.Z, literal.x, +; R600-NEXT: CNDE_INT T0.Z, T3.Z, T2.W, PV.Y, BS:VEC_120/SCL_212 +; R600-NEXT: CNDE_INT T1.W, T5.W, PV.X, T1.W, BS:VEC_021/SCL_122 +; R600-NEXT: LSHL * T2.W, T1.Y, literal.y, ; R600-NEXT: 127(1.779649e-43), 23(3.222986e-44) -; R600-NEXT: ADD_INT T7.X, PS, literal.x, -; R600-NEXT: CNDE_INT T0.Y, T1.Z, PV.Z, PV.W, -; R600-NEXT: CNDE_INT T0.Z, PV.Y, T6.X, PV.X, -; R600-NEXT: MUL_IEEE T0.W, T4.X, literal.y, -; R600-NEXT: CNDE_INT * T1.W, T5.X, T2.Y, T1.W, -; R600-NEXT: 1065353216(1.000000e+00), 2130706432(1.701412e+38) -; R600-NEXT: CNDE_INT T5.X, T3.W, PS, T1.Y, -; R600-NEXT: CNDE_INT * T1.Y, T2.W, T4.X, PV.W, BS:VEC_120/SCL_212 -; R600-NEXT: ALU clause starting at 201: +; R600-NEXT: ADD_INT T8.X, PS, literal.x, +; R600-NEXT: CNDE_INT T1.Y, T2.Z, PV.W, PV.Z, +; R600-NEXT: CNDE_INT T0.Z, PV.Y, T7.X, PV.X, +; R600-NEXT: CNDE_INT * T0.W, T6.X, T5.X, T0.W, BS:VEC_021/SCL_122 +; R600-NEXT: 1065353216(1.000000e+00), 0(0.000000e+00) +; R600-NEXT: MUL_IEEE * T1.W, T4.X, literal.x, +; R600-NEXT: 2130706432(1.701412e+38), 0(0.000000e+00) +; R600-NEXT: CNDE_INT T4.X, T6.W, T4.X, PV.W, +; R600-NEXT: CNDE_INT * T2.Y, T4.W, T0.W, T1.X, BS:VEC_120/SCL_212 +; R600-NEXT: ALU clause starting at 204: ; R600-NEXT: LSHL T0.Z, T0.Z, literal.x, -; R600-NEXT: MUL_IEEE T0.W, T0.Y, T7.X, +; R600-NEXT: MUL_IEEE T0.W, T1.Y, T8.X, ; R600-NEXT: SETGT * T1.W, literal.y, KC0[3].W, ; R600-NEXT: 23(3.222986e-44), -1036817932(-4.485347e+01) -; R600-NEXT: CNDE T4.X, PS, PV.W, 0.0, -; R600-NEXT: SETGT T0.Y, KC0[3].W, literal.x, +; R600-NEXT: CNDE T1.X, PS, PV.W, 0.0, +; R600-NEXT: SETGT T1.Y, KC0[3].W, literal.x, ; R600-NEXT: ADD_INT T0.Z, PV.Z, literal.y, -; R600-NEXT: CNDE_INT T0.W, T5.Y, T5.X, T1.Y, BS:VEC_102/SCL_221 -; R600-NEXT: CNDE * T1.W, T0.X, T3.X, literal.z, +; R600-NEXT: CNDE_INT T0.W, T3.Y, T2.Y, T4.X, BS:VEC_120/SCL_212 +; R600-NEXT: CNDE * T1.W, T2.X, T3.X, literal.z, ; R600-NEXT: 1109008539(3.853184e+01), 1065353216(1.000000e+00) ; R600-NEXT: 2139095040(INF), 0(0.000000e+00) -; R600-NEXT: MUL_IEEE T0.X, PV.W, PV.Z, +; R600-NEXT: MUL_IEEE T2.X, PV.W, PV.Z, ; R600-NEXT: SETGT T2.Y, literal.x, KC0[3].Y, ; R600-NEXT: CNDE T1.Z, PV.Y, PV.X, literal.y, -; R600-NEXT: CNDE T0.W, T2.X, T1.X, 0.0, +; R600-NEXT: CNDE T0.W, T0.X, T0.Y, 0.0, ; R600-NEXT: SETGT * T2.W, KC0[3].Z, literal.z, ; R600-NEXT: -1036817932(-4.485347e+01), 2139095040(INF) ; R600-NEXT: 1109008539(3.853184e+01), 0(0.000000e+00) @@ -2275,8 +2287,8 @@ define amdgpu_kernel void @s_exp10_v4f32(ptr addrspace(1) %out, <4 x float> %in) ; CM-LABEL: s_exp10_v4f32: ; CM: ; %bb.0: ; CM-NEXT: ALU 97, @6, KC0[CB0:0-32], KC1[] -; CM-NEXT: ALU 97, @104, KC0[CB0:0-32], KC1[] -; CM-NEXT: ALU 35, @202, KC0[CB0:0-32], KC1[] +; CM-NEXT: ALU 100, @104, KC0[CB0:0-32], KC1[] +; CM-NEXT: ALU 36, @205, KC0[CB0:0-32], KC1[] ; CM-NEXT: MEM_RAT_CACHELESS STORE_DWORD T0, T1.X ; CM-NEXT: CF_END ; CM-NEXT: PAD @@ -2295,220 +2307,224 @@ define amdgpu_kernel void @s_exp10_v4f32(ptr addrspace(1) %out, <4 x float> %in) ; CM-NEXT: 1079283712(3.321289e+00), 0(0.000000e+00) ; CM-NEXT: MULADD_IEEE T0.X, T0.W, literal.x, PV.W, ; CM-NEXT: ADD T0.Y, T0.Z, -PV.Z, -; CM-NEXT: MUL_IEEE T0.Z, T2.W, literal.y, BS:VEC_120/SCL_212 -; CM-NEXT: MUL_IEEE * T0.W, PV.Y, literal.x, +; CM-NEXT: MUL_IEEE T0.Z, PV.Y, literal.x, +; CM-NEXT: MUL_IEEE * T0.W, T2.W, literal.y, BS:VEC_120/SCL_212 ; CM-NEXT: 975668412(6.390323e-04), 1079283712(3.321289e+00) ; CM-NEXT: TRUNC T1.X, T1.Z, -; CM-NEXT: MULADD_IEEE T1.Y, T1.Y, literal.x, PV.W, -; CM-NEXT: RNDNE T1.Z, PV.Z, -; CM-NEXT: ADD * T0.W, PV.Y, PV.X, +; CM-NEXT: RNDNE T2.Y, PV.W, +; CM-NEXT: MULADD_IEEE T0.Z, T1.Y, literal.x, PV.Z, +; CM-NEXT: ADD * T1.W, PV.Y, PV.X, ; CM-NEXT: 1079283712(3.321289e+00), 0(0.000000e+00) -; CM-NEXT: EXP_IEEE T0.X, T0.W, -; CM-NEXT: EXP_IEEE T0.Y (MASKED), T0.W, -; CM-NEXT: EXP_IEEE T0.Z (MASKED), T0.W, -; CM-NEXT: EXP_IEEE * T0.W (MASKED), T0.W, -; CM-NEXT: TRUNC T2.X, T1.Z, -; CM-NEXT: MULADD_IEEE T0.Y, T2.W, literal.x, T1.Y, -; CM-NEXT: FLT_TO_INT T2.Z, T1.X, -; CM-NEXT: MUL_IEEE * T0.W, PV.X, literal.y, -; CM-NEXT: 975668412(6.390323e-04), 209715200(1.972152e-31) -; CM-NEXT: ADD T1.X, T0.Z, -T1.Z, -; CM-NEXT: MUL_IEEE T1.Y, PV.W, literal.x, -; CM-NEXT: MAX_INT T0.Z, PV.Z, literal.y, -; CM-NEXT: MIN_INT * T1.W, PV.Z, literal.z, -; CM-NEXT: 209715200(1.972152e-31), -330(nan) -; CM-NEXT: 381(5.338947e-43), 0(0.000000e+00) -; CM-NEXT: ADD_INT T3.X, PV.W, literal.x, -; CM-NEXT: ADD_INT T2.Y, PV.Z, literal.y, -; CM-NEXT: ADD_INT T0.Z, T2.Z, literal.z, -; CM-NEXT: SETGT_UINT * T1.W, T2.Z, literal.w, -; CM-NEXT: -254(nan), 204(2.858649e-43) -; CM-NEXT: 102(1.429324e-43), -229(nan) -; CM-NEXT: ADD_INT T4.X, T2.Z, literal.x, -; CM-NEXT: SETGT_UINT T3.Y, T2.Z, literal.y, -; CM-NEXT: CNDE_INT T0.Z, PV.W, PV.Y, PV.Z, -; CM-NEXT: SETGT_INT * T2.W, T2.Z, literal.x, -; CM-NEXT: -127(nan), 254(3.559298e-43) -; CM-NEXT: MUL_IEEE T5.X, T0.X, literal.x, -; CM-NEXT: CNDE_INT T2.Y, PV.W, PV.Z, T2.Z, -; CM-NEXT: CNDE_INT T0.Z, PV.Y, PV.X, T3.X, -; CM-NEXT: SETGT_INT * T3.W, T2.Z, literal.y, -; CM-NEXT: 2130706432(1.701412e+38), 127(1.779649e-43) -; CM-NEXT: AND_INT T3.X, KC0[3].Z, literal.x, -; CM-NEXT: CNDE_INT T2.Y, PV.W, PV.Y, PV.Z, -; CM-NEXT: MUL_IEEE T0.Z, PV.X, literal.y, -; CM-NEXT: CNDE_INT * T0.W, T1.W, T1.Y, T0.W, -; CM-NEXT: -4096(nan), 2130706432(1.701412e+38) -; CM-NEXT: CNDE_INT T0.X, T2.W, PV.W, T0.X, -; CM-NEXT: CNDE_INT T1.Y, T3.Y, T5.X, PV.Z, -; CM-NEXT: LSHL T0.Z, PV.Y, literal.x, -; CM-NEXT: MUL_IEEE * T0.W, PV.X, literal.y, -; CM-NEXT: 23(3.222986e-44), 1079283712(3.321289e+00) -; CM-NEXT: RNDNE T4.X, PV.W, -; CM-NEXT: ADD_INT T2.Y, PV.Z, literal.x, -; CM-NEXT: CNDE_INT T0.Z, T3.W, PV.X, PV.Y, -; CM-NEXT: ADD * T1.W, T1.X, T0.Y, -; CM-NEXT: 1065353216(1.000000e+00), 0(0.000000e+00) ; CM-NEXT: EXP_IEEE T0.X, T1.W, ; CM-NEXT: EXP_IEEE T0.Y (MASKED), T1.W, ; CM-NEXT: EXP_IEEE T0.Z (MASKED), T1.W, ; CM-NEXT: EXP_IEEE * T0.W (MASKED), T1.W, -; CM-NEXT: MUL_IEEE T1.X, T0.Z, T2.Y, -; CM-NEXT: TRUNC T0.Y, T4.X, -; CM-NEXT: FLT_TO_INT T0.Z, T2.X, BS:VEC_120/SCL_212 -; CM-NEXT: MUL_IEEE * T1.W, PV.X, literal.x, -; CM-NEXT: 209715200(1.972152e-31), 0(0.000000e+00) -; CM-NEXT: MUL_IEEE T2.X, PV.W, literal.x, +; CM-NEXT: MULADD_IEEE T2.X, T2.W, literal.x, T0.Z, +; CM-NEXT: ADD T0.Y, T0.W, -T2.Y, BS:VEC_120/SCL_212 +; CM-NEXT: FLT_TO_INT T0.Z, T1.X, +; CM-NEXT: MUL_IEEE * T0.W, PV.X, literal.y, +; CM-NEXT: 975668412(6.390323e-04), 209715200(1.972152e-31) +; CM-NEXT: MUL_IEEE T1.X, PV.W, literal.x, ; CM-NEXT: MUL_IEEE T1.Y, T0.X, literal.y, ; CM-NEXT: MAX_INT T1.Z, PV.Z, literal.z, -; CM-NEXT: MIN_INT * T2.W, PV.Z, literal.w, +; CM-NEXT: MIN_INT * T1.W, PV.Z, literal.w, ; CM-NEXT: 209715200(1.972152e-31), 2130706432(1.701412e+38) ; CM-NEXT: -330(nan), 381(5.338947e-43) -; CM-NEXT: ADD_INT T5.X, PV.W, literal.x, -; CM-NEXT: ADD_INT T2.Y, PV.Z, literal.y, +; CM-NEXT: ADD_INT T3.X, PV.W, literal.x, +; CM-NEXT: ADD_INT T3.Y, PV.Z, literal.y, ; CM-NEXT: ADD_INT T1.Z, T0.Z, literal.z, -; CM-NEXT: SETGT_UINT * T2.W, T0.Z, literal.w, +; CM-NEXT: SETGT_UINT * T1.W, T0.Z, literal.w, ; CM-NEXT: -254(nan), 204(2.858649e-43) ; CM-NEXT: 102(1.429324e-43), -229(nan) -; CM-NEXT: ADD_INT T6.X, T0.Z, literal.x, -; CM-NEXT: SETGT_UINT T3.Y, T0.Z, literal.y, +; CM-NEXT: ADD_INT T4.X, T0.Z, literal.x, +; CM-NEXT: SETGT_UINT T4.Y, T0.Z, literal.y, ; CM-NEXT: CNDE_INT T1.Z, PV.W, PV.Y, PV.Z, -; CM-NEXT: SETGT_INT * T3.W, T0.Z, literal.x, +; CM-NEXT: SETGT_INT * T2.W, T0.Z, literal.x, ; CM-NEXT: -127(nan), 254(3.559298e-43) -; CM-NEXT: CNDE_INT T7.X, PV.W, PV.Z, T0.Z, -; CM-NEXT: CNDE_INT T2.Y, PV.Y, PV.X, T5.X, -; CM-NEXT: SETGT_INT * T0.Z, T0.Z, literal.x, -; CM-NEXT: 127(1.779649e-43), 0(0.000000e+00) -; CM-NEXT: ALU clause starting at 104: -; CM-NEXT: ADD * T4.W, KC0[3].Z, -T3.X, -; CM-NEXT: MUL_IEEE T5.X, PV.W, literal.x, -; CM-NEXT: CNDE_INT T2.Y, T0.Z, T7.X, T2.Y, -; CM-NEXT: MUL_IEEE T1.Z, T1.Y, literal.y, -; CM-NEXT: CNDE_INT * T1.W, T2.W, T2.X, T1.W, BS:VEC_021/SCL_122 -; CM-NEXT: 975668412(6.390323e-04), 2130706432(1.701412e+38) -; CM-NEXT: CNDE_INT T0.X, T3.W, PV.W, T0.X, -; CM-NEXT: CNDE_INT T1.Y, T3.Y, T1.Y, PV.Z, -; CM-NEXT: LSHL T1.Z, PV.Y, literal.x, -; CM-NEXT: MULADD_IEEE * T1.W, T4.W, literal.y, PV.X, BS:VEC_120/SCL_212 -; CM-NEXT: 23(3.222986e-44), 1079283712(3.321289e+00) -; CM-NEXT: MULADD_IEEE T2.X, T3.X, literal.x, PV.W, -; CM-NEXT: ADD T2.Y, T0.W, -T4.X, -; CM-NEXT: ADD_INT T1.Z, PV.Z, literal.y, -; CM-NEXT: CNDE_INT * T0.W, T0.Z, PV.X, PV.Y, +; CM-NEXT: CNDE_INT T5.X, PV.W, PV.Z, T0.Z, +; CM-NEXT: CNDE_INT T3.Y, PV.Y, PV.X, T3.X, +; CM-NEXT: SETGT_INT T0.Z, T0.Z, literal.x, +; CM-NEXT: MUL_IEEE * T3.W, T1.Y, literal.y, +; CM-NEXT: 127(1.779649e-43), 2130706432(1.701412e+38) +; CM-NEXT: CNDE_INT T3.X, T4.Y, T1.Y, PV.W, +; CM-NEXT: AND_INT T1.Y, KC0[3].Z, literal.x, +; CM-NEXT: CNDE_INT T1.Z, PV.Z, PV.X, PV.Y, +; CM-NEXT: CNDE_INT * T0.W, T1.W, T1.X, T0.W, +; CM-NEXT: -4096(nan), 0(0.000000e+00) +; CM-NEXT: CNDE_INT T0.X, T2.W, PV.W, T0.X, +; CM-NEXT: LSHL T3.Y, PV.Z, literal.x, +; CM-NEXT: TRUNC T1.Z, T2.Y, +; CM-NEXT: ADD * T0.W, KC0[3].Z, -PV.Y, +; CM-NEXT: 23(3.222986e-44), 0(0.000000e+00) +; CM-NEXT: MUL_IEEE T1.X, PV.W, literal.x, +; CM-NEXT: FLT_TO_INT T2.Y, PV.Z, +; CM-NEXT: ADD_INT T1.Z, PV.Y, literal.y, +; CM-NEXT: CNDE_INT * T1.W, T0.Z, PV.X, T3.X, ; CM-NEXT: 975668412(6.390323e-04), 1065353216(1.000000e+00) -; CM-NEXT: AND_INT T0.X, KC0[4].X, literal.x, -; CM-NEXT: MUL_IEEE T1.Y, PV.W, PV.Z, -; CM-NEXT: SETGT T0.Z, literal.y, KC0[3].W, -; CM-NEXT: ADD * T0.W, PV.Y, PV.X, -; CM-NEXT: -4096(nan), -1036817932(-4.485347e+01) +; CM-NEXT: MUL_IEEE T0.X, PV.W, PV.Z, +; CM-NEXT: MIN_INT T3.Y, PV.Y, literal.x, +; CM-NEXT: MULADD_IEEE T0.Z, T0.W, literal.y, PV.X, +; CM-NEXT: ADD * T0.W, T0.Y, T2.X, +; CM-NEXT: 381(5.338947e-43), 1079283712(3.321289e+00) +; CM-NEXT: EXP_IEEE T0.X (MASKED), T0.W, +; CM-NEXT: EXP_IEEE T0.Y, T0.W, +; CM-NEXT: EXP_IEEE T0.Z (MASKED), T0.W, +; CM-NEXT: EXP_IEEE * T0.W (MASKED), T0.W, +; CM-NEXT: MULADD_IEEE T1.X, T1.Y, literal.x, T0.Z, +; CM-NEXT: MUL_IEEE T4.Y, PV.Y, literal.y, +; CM-NEXT: ADD_INT T0.Z, T3.Y, literal.z, BS:VEC_120/SCL_212 +; CM-NEXT: MAX_INT * T0.W, T2.Y, literal.w, BS:VEC_201 +; CM-NEXT: 975668412(6.390323e-04), 2130706432(1.701412e+38) +; CM-NEXT: -254(nan), -330(nan) +; CM-NEXT: ADD_INT T2.X, T2.Y, literal.x, +; CM-NEXT: ADD_INT T3.Y, PV.W, literal.y, +; CM-NEXT: ADD_INT T1.Z, T2.Y, literal.z, +; CM-NEXT: SETGT_UINT * T0.W, T2.Y, literal.w, +; CM-NEXT: -127(nan), 204(2.858649e-43) +; CM-NEXT: 102(1.429324e-43), -229(nan) +; CM-NEXT: SETGT_UINT T3.X, T2.Y, literal.x, +; CM-NEXT: CNDE_INT T3.Y, PV.W, PV.Y, PV.Z, +; CM-NEXT: SETGT_INT T1.Z, T2.Y, literal.y, +; CM-NEXT: MUL_IEEE * T1.W, T0.Y, literal.z, BS:VEC_120/SCL_212 +; CM-NEXT: 254(3.559298e-43), -127(nan) +; CM-NEXT: 209715200(1.972152e-31), 0(0.000000e+00) +; CM-NEXT: MUL_IEEE T4.X, PV.W, literal.x, +; CM-NEXT: CNDE_INT * T3.Y, PV.Z, PV.Y, T2.Y, +; CM-NEXT: 209715200(1.972152e-31), 0(0.000000e+00) +; CM-NEXT: ALU clause starting at 104: +; CM-NEXT: CNDE_INT T0.Z, T3.X, T2.X, T0.Z, +; CM-NEXT: SETGT_INT * T2.W, T2.Y, literal.x, +; CM-NEXT: 127(1.779649e-43), 0(0.000000e+00) +; CM-NEXT: MUL_IEEE T2.X, T1.Y, literal.x, +; CM-NEXT: CNDE_INT T1.Y, PV.W, T3.Y, PV.Z, +; CM-NEXT: CNDE_INT T0.Z, T0.W, T4.X, T1.W, +; CM-NEXT: MUL_IEEE * T0.W, T4.Y, literal.y, BS:VEC_201 +; CM-NEXT: 1079283712(3.321289e+00), 2130706432(1.701412e+38) +; CM-NEXT: AND_INT T4.X, KC0[4].X, literal.x, +; CM-NEXT: CNDE_INT T2.Y, T3.X, T4.Y, PV.W, +; CM-NEXT: CNDE_INT T0.Z, T1.Z, PV.Z, T0.Y, +; CM-NEXT: LSHL * T0.W, PV.Y, literal.y, +; CM-NEXT: -4096(nan), 23(3.222986e-44) +; CM-NEXT: ADD_INT T3.X, PV.W, literal.x, +; CM-NEXT: CNDE_INT T0.Y, T2.W, PV.Z, PV.Y, +; CM-NEXT: MUL_IEEE T0.Z, PV.X, literal.y, +; CM-NEXT: RNDNE * T0.W, T2.X, +; CM-NEXT: 1065353216(1.000000e+00), 1079283712(3.321289e+00) +; CM-NEXT: ADD T2.X, T2.X, -PV.W, +; CM-NEXT: RNDNE T1.Y, PV.Z, +; CM-NEXT: MUL_IEEE T1.Z, PV.Y, PV.X, +; CM-NEXT: SETGT * T1.W, literal.x, KC0[3].W, +; CM-NEXT: -1036817932(-4.485347e+01), 0(0.000000e+00) +; CM-NEXT: CNDE T3.X, PV.W, PV.Z, 0.0, +; CM-NEXT: TRUNC T0.Y, T0.W, +; CM-NEXT: TRUNC T1.Z, PV.Y, +; CM-NEXT: ADD * T0.W, PV.X, T1.X, ; CM-NEXT: EXP_IEEE T0.X (MASKED), T0.W, ; CM-NEXT: EXP_IEEE T0.Y (MASKED), T0.W, ; CM-NEXT: EXP_IEEE T0.Z (MASKED), T0.W, ; CM-NEXT: EXP_IEEE * T0.W, T0.W, -; CM-NEXT: CNDE T2.X, T0.Z, T1.Y, 0.0, -; CM-NEXT: ADD T1.Y, KC0[4].X, -T0.X, -; CM-NEXT: FLT_TO_INT T0.Z, T0.Y, -; CM-NEXT: MUL_IEEE * T1.W, PV.W, literal.x, -; CM-NEXT: 209715200(1.972152e-31), 0(0.000000e+00) -; CM-NEXT: MUL_IEEE T3.X, PV.W, literal.x, -; CM-NEXT: SETGT_UINT T0.Y, PV.Z, literal.y, -; CM-NEXT: MUL_IEEE T1.Z, PV.Y, literal.z, -; CM-NEXT: MUL_IEEE * T2.W, T0.X, literal.w, -; CM-NEXT: 209715200(1.972152e-31), -229(nan) -; CM-NEXT: 975668412(6.390323e-04), 1079283712(3.321289e+00) -; CM-NEXT: RNDNE T4.X, PV.W, -; CM-NEXT: MULADD_IEEE T1.Y, T1.Y, literal.x, PV.Z, -; CM-NEXT: CNDE_INT T1.Z, PV.Y, PV.X, T1.W, -; CM-NEXT: SETGT_INT * T1.W, T0.Z, literal.y, -; CM-NEXT: 1079283712(3.321289e+00), -127(nan) -; CM-NEXT: CNDE_INT T3.X, PV.W, PV.Z, T0.W, -; CM-NEXT: MULADD_IEEE T1.Y, T0.X, literal.x, PV.Y, -; CM-NEXT: ADD T1.Z, T2.W, -PV.X, -; CM-NEXT: MAX_INT * T2.W, T0.Z, literal.y, +; CM-NEXT: FLT_TO_INT T1.X, T1.Z, +; CM-NEXT: FLT_TO_INT T0.Y, T0.Y, +; CM-NEXT: MUL_IEEE T1.Z, PV.W, literal.x, +; CM-NEXT: ADD * T1.W, KC0[4].X, -T4.X, +; CM-NEXT: 2130706432(1.701412e+38), 0(0.000000e+00) +; CM-NEXT: MUL_IEEE T2.X, PV.W, literal.x, +; CM-NEXT: MUL_IEEE T2.Y, T0.W, literal.y, +; CM-NEXT: MUL_IEEE T2.Z, PV.Z, literal.z, +; CM-NEXT: SETGT_UINT * T2.W, PV.Y, literal.w, +; CM-NEXT: 975668412(6.390323e-04), 209715200(1.972152e-31) +; CM-NEXT: 2130706432(1.701412e+38), 254(3.559298e-43) +; CM-NEXT: CNDE_INT T5.X, PV.W, T1.Z, PV.Z, +; CM-NEXT: MUL_IEEE T3.Y, PV.Y, literal.x, +; CM-NEXT: MULADD_IEEE T1.Z, T1.W, literal.y, PV.X, +; CM-NEXT: MAX_INT * T1.W, T1.X, literal.z, +; CM-NEXT: 209715200(1.972152e-31), 1079283712(3.321289e+00) +; CM-NEXT: -330(nan), 0(0.000000e+00) +; CM-NEXT: ADD_INT T2.X, PV.W, literal.x, +; CM-NEXT: ADD_INT T4.Y, T1.X, literal.y, +; CM-NEXT: MULADD_IEEE T1.Z, T4.X, literal.z, PV.Z, BS:VEC_120/SCL_212 +; CM-NEXT: MAX_INT * T1.W, T0.Y, literal.w, +; CM-NEXT: 204(2.858649e-43), 102(1.429324e-43) ; CM-NEXT: 975668412(6.390323e-04), -330(nan) -; CM-NEXT: ADD_INT T0.X, PV.W, literal.x, -; CM-NEXT: ADD_INT T2.Y, T0.Z, literal.y, -; CM-NEXT: TRUNC T2.Z, T4.X, -; CM-NEXT: ADD * T2.W, PV.Z, PV.Y, +; CM-NEXT: ADD T4.X, T0.Z, -T1.Y, +; CM-NEXT: ADD_INT T1.Y, PV.W, literal.x, +; CM-NEXT: ADD_INT T0.Z, T0.Y, literal.y, +; CM-NEXT: SETGT_UINT * T1.W, T0.Y, literal.z, ; CM-NEXT: 204(2.858649e-43), 102(1.429324e-43) -; CM-NEXT: EXP_IEEE T1.X (MASKED), T2.W, -; CM-NEXT: EXP_IEEE T1.Y, T2.W, -; CM-NEXT: EXP_IEEE T1.Z (MASKED), T2.W, -; CM-NEXT: EXP_IEEE * T1.W (MASKED), T2.W, -; CM-NEXT: MUL_IEEE T4.X, T0.W, literal.x, -; CM-NEXT: FLT_TO_INT T3.Y, T2.Z, -; CM-NEXT: MUL_IEEE T1.Z, PV.Y, literal.y, -; CM-NEXT: CNDE_INT * T0.W, T0.Y, T0.X, T2.Y, +; CM-NEXT: -229(nan), 0(0.000000e+00) +; CM-NEXT: SETGT_UINT T6.X, T1.X, literal.x, +; CM-NEXT: CNDE_INT T1.Y, PV.W, PV.Y, PV.Z, +; CM-NEXT: SETGT_INT T0.Z, T0.Y, literal.y, +; CM-NEXT: ADD * T3.W, PV.X, T1.Z, +; CM-NEXT: -229(nan), -127(nan) +; CM-NEXT: EXP_IEEE T1.X (MASKED), T3.W, +; CM-NEXT: EXP_IEEE T1.Y (MASKED), T3.W, +; CM-NEXT: EXP_IEEE T1.Z, T3.W, +; CM-NEXT: EXP_IEEE * T1.W (MASKED), T3.W, +; CM-NEXT: CNDE_INT T4.X, T0.Z, T1.Y, T0.Y, +; CM-NEXT: CNDE_INT T1.Y, T6.X, T2.X, T4.Y, BS:VEC_120/SCL_212 +; CM-NEXT: SETGT_INT T2.Z, T1.X, literal.x, +; CM-NEXT: MUL_IEEE * T3.W, PV.Z, literal.y, +; CM-NEXT: -127(nan), 209715200(1.972152e-31) +; CM-NEXT: MUL_IEEE T2.X, T1.Z, literal.x, +; CM-NEXT: MUL_IEEE T4.Y, PV.W, literal.y, +; CM-NEXT: CNDE_INT T3.Z, PV.Z, PV.Y, T1.X, +; CM-NEXT: MIN_INT * T4.W, T1.X, literal.z, ; CM-NEXT: 2130706432(1.701412e+38), 209715200(1.972152e-31) -; CM-NEXT: CNDE_INT T0.X, T1.W, PV.W, T0.Z, -; CM-NEXT: MUL_IEEE T0.Y, PV.Z, literal.x, -; CM-NEXT: MAX_INT T2.Z, PV.Y, literal.y, -; CM-NEXT: MIN_INT * T0.W, PV.Y, literal.z, -; CM-NEXT: 209715200(1.972152e-31), -330(nan) ; CM-NEXT: 381(5.338947e-43), 0(0.000000e+00) -; CM-NEXT: ADD_INT T5.X, PV.W, literal.x, -; CM-NEXT: ADD_INT T2.Y, PV.Z, literal.y, -; CM-NEXT: ADD_INT T2.Z, T3.Y, literal.z, -; CM-NEXT: SETGT_UINT * T0.W, T3.Y, literal.w, -; CM-NEXT: -254(nan), 204(2.858649e-43) -; CM-NEXT: 102(1.429324e-43), -229(nan) -; CM-NEXT: ADD_INT T6.X, T3.Y, literal.x, -; CM-NEXT: SETGT_UINT T4.Y, T3.Y, literal.y, -; CM-NEXT: CNDE_INT T2.Z, PV.W, PV.Y, PV.Z, -; CM-NEXT: SETGT_INT * T1.W, T3.Y, literal.x, +; CM-NEXT: MIN_INT T7.X, T0.Y, literal.x, +; CM-NEXT: ADD_INT T1.Y, PV.W, literal.y, +; CM-NEXT: ADD_INT T4.Z, T1.X, literal.z, +; CM-NEXT: SETGT_UINT * T4.W, T1.X, literal.w, +; CM-NEXT: 381(5.338947e-43), -254(nan) ; CM-NEXT: -127(nan), 254(3.559298e-43) -; CM-NEXT: MUL_IEEE T7.X, T1.Y, literal.x, -; CM-NEXT: CNDE_INT T2.Y, PV.W, PV.Z, T3.Y, -; CM-NEXT: CNDE_INT T2.Z, PV.Y, PV.X, T5.X, -; CM-NEXT: MIN_INT * T2.W, T0.Z, literal.y, -; CM-NEXT: 2130706432(1.701412e+38), 381(5.338947e-43) -; CM-NEXT: SETGT_INT T5.X, T3.Y, literal.x, -; CM-NEXT: ADD_INT T3.Y, PV.W, literal.y, -; CM-NEXT: ADD_INT T3.Z, T0.Z, literal.z, -; CM-NEXT: SETGT_UINT * T2.W, T0.Z, literal.w, +; CM-NEXT: CNDE_INT T8.X, PV.W, PV.Z, PV.Y, +; CM-NEXT: SETGT_INT T1.Y, T1.X, literal.x, +; CM-NEXT: ADD_INT T4.Z, PV.X, literal.y, +; CM-NEXT: ADD_INT * T5.W, T0.Y, literal.z, ; CM-NEXT: 127(1.779649e-43), -254(nan) -; CM-NEXT: -127(nan), 254(3.559298e-43) -; CM-NEXT: CNDE_INT T6.X, PV.W, PV.Z, PV.Y, -; CM-NEXT: CNDE_INT T2.Y, PV.X, T2.Y, T2.Z, -; CM-NEXT: MUL_IEEE T2.Z, T7.X, literal.x, -; CM-NEXT: CNDE_INT * T0.W, T0.W, T0.Y, T1.Z, BS:VEC_021/SCL_122 +; CM-NEXT: -127(nan), 0(0.000000e+00) +; CM-NEXT: CNDE_INT T1.X, T2.W, PV.W, PV.Z, +; CM-NEXT: CNDE_INT T5.Y, PV.Y, T3.Z, PV.X, +; CM-NEXT: CNDE_INT T3.Z, T6.X, T4.Y, T3.W, +; CM-NEXT: MUL_IEEE * T2.W, T2.X, literal.x, BS:VEC_120/SCL_212 ; CM-NEXT: 2130706432(1.701412e+38), 0(0.000000e+00) -; CM-NEXT: SETGT_INT T8.X, T0.Z, literal.x, -; CM-NEXT: CNDE_INT T0.Y, T1.W, PV.W, T1.Y, -; CM-NEXT: CNDE_INT T0.Z, T4.Y, T7.X, PV.Z, -; CM-NEXT: LSHL * T0.W, PV.Y, literal.y, -; CM-NEXT: 127(1.779649e-43), 23(3.222986e-44) -; CM-NEXT: ALU clause starting at 202: -; CM-NEXT: ADD_INT T7.X, T0.W, literal.x, -; CM-NEXT: CNDE_INT * T0.Y, T5.X, T0.Y, T0.Z, +; CM-NEXT: SETGT_INT T6.X, T0.Y, literal.x, +; CM-NEXT: CNDE_INT T0.Y, T4.W, T2.X, PV.W, +; CM-NEXT: CNDE_INT * T1.Z, T2.Z, PV.Z, T1.Z, +; CM-NEXT: 127(1.779649e-43), 0(0.000000e+00) +; CM-NEXT: ALU clause starting at 205: +; CM-NEXT: LSHL * T2.W, T5.Y, literal.x, +; CM-NEXT: 23(3.222986e-44), 0(0.000000e+00) +; CM-NEXT: ADD_INT T2.X, PV.W, literal.x, +; CM-NEXT: CNDE_INT T0.Y, T1.Y, T1.Z, T0.Y, +; CM-NEXT: CNDE_INT * T1.Z, T6.X, T4.X, T1.X, ; CM-NEXT: 1065353216(1.000000e+00), 0(0.000000e+00) -; CM-NEXT: CNDE_INT * T0.Z, T8.X, T0.X, T6.X, -; CM-NEXT: MUL_IEEE * T0.W, T4.X, literal.x, -; CM-NEXT: 2130706432(1.701412e+38), 0(0.000000e+00) -; CM-NEXT: CNDE_INT T0.X, T2.W, T4.X, PV.W, -; CM-NEXT: LSHL T1.Y, T0.Z, literal.x, -; CM-NEXT: MUL_IEEE T0.Z, T0.Y, T7.X, BS:VEC_021/SCL_122 +; CM-NEXT: CNDE_INT * T1.W, T1.W, T3.Y, T2.Y, +; CM-NEXT: CNDE_INT T1.X, T0.Z, PV.W, T0.W, +; CM-NEXT: LSHL T1.Y, T1.Z, literal.x, BS:VEC_120/SCL_212 +; CM-NEXT: MUL_IEEE T0.Z, T0.Y, T2.X, ; CM-NEXT: SETGT * T0.W, literal.y, KC0[4].X, ; CM-NEXT: 23(3.222986e-44), -1036817932(-4.485347e+01) -; CM-NEXT: CNDE T4.X, PV.W, PV.Z, 0.0, +; CM-NEXT: CNDE T2.X, PV.W, PV.Z, 0.0, ; CM-NEXT: SETGT T0.Y, KC0[4].X, literal.x, ; CM-NEXT: ADD_INT T0.Z, PV.Y, literal.y, -; CM-NEXT: CNDE_INT * T0.W, T8.X, T3.X, PV.X, +; CM-NEXT: CNDE_INT * T0.W, T6.X, PV.X, T5.X, ; CM-NEXT: 1109008539(3.853184e+01), 1065353216(1.000000e+00) -; CM-NEXT: SETGT T0.X, KC0[3].W, literal.x, +; CM-NEXT: SETGT T1.X, KC0[3].W, literal.x, ; CM-NEXT: MUL_IEEE T1.Y, PV.W, PV.Z, ; CM-NEXT: SETGT T0.Z, literal.y, KC0[3].Z, ; CM-NEXT: CNDE * T0.W, PV.Y, PV.X, literal.z, ; CM-NEXT: 1109008539(3.853184e+01), -1036817932(-4.485347e+01) ; CM-NEXT: 2139095040(INF), 0(0.000000e+00) -; CM-NEXT: SETGT T3.X, literal.x, KC0[3].Y, +; CM-NEXT: SETGT T2.X, literal.x, KC0[3].Y, ; CM-NEXT: CNDE T0.Y, PV.Z, PV.Y, 0.0, -; CM-NEXT: CNDE T0.Z, PV.X, T2.X, literal.y, +; CM-NEXT: CNDE T0.Z, PV.X, T3.X, literal.y, ; CM-NEXT: SETGT * T1.W, KC0[3].Z, literal.z, ; CM-NEXT: -1036817932(-4.485347e+01), 2139095040(INF) ; CM-NEXT: 1109008539(3.853184e+01), 0(0.000000e+00) ; CM-NEXT: CNDE T0.Y, PV.W, PV.Y, literal.x, -; CM-NEXT: CNDE T1.Z, PV.X, T1.X, 0.0, +; CM-NEXT: CNDE T1.Z, PV.X, T0.X, 0.0, ; CM-NEXT: SETGT * T1.W, KC0[3].Y, literal.y, ; CM-NEXT: 2139095040(INF), 1109008539(3.853184e+01) ; CM-NEXT: CNDE * T0.X, PV.W, PV.Z, literal.x, diff --git a/llvm/test/CodeGen/AMDGPU/shl.ll b/llvm/test/CodeGen/AMDGPU/shl.ll index b3f4790df4d4..b1a82daa8e7d 100644 --- a/llvm/test/CodeGen/AMDGPU/shl.ll +++ b/llvm/test/CodeGen/AMDGPU/shl.ll @@ -795,17 +795,17 @@ define amdgpu_kernel void @shl_i64(ptr addrspace(1) %out, ptr addrspace(1) %in) ; EG-NEXT: ALU clause starting at 8: ; EG-NEXT: MOV * T0.X, KC0[2].Z, ; EG-NEXT: ALU clause starting at 9: -; EG-NEXT: LSHR T1.Y, T0.Y, 1, -; EG-NEXT: NOT_INT T1.Z, T0.Z, +; EG-NEXT: AND_INT T1.Y, T0.Z, literal.x, +; EG-NEXT: LSHR T1.Z, T0.Y, 1, ; EG-NEXT: BIT_ALIGN_INT T0.W, T0.Y, T0.X, 1, -; EG-NEXT: AND_INT * T1.W, T0.Z, literal.x, +; EG-NEXT: NOT_INT * T1.W, T0.Z, ; EG-NEXT: 31(4.344025e-44), 0(0.000000e+00) -; EG-NEXT: LSHL T2.Z, T0.X, PS, -; EG-NEXT: BIT_ALIGN_INT T0.W, PV.Y, PV.W, PV.Z, +; EG-NEXT: BIT_ALIGN_INT T1.Z, PV.Z, PV.W, PS, +; EG-NEXT: LSHL T0.W, T0.X, PV.Y, ; EG-NEXT: AND_INT * T1.W, T0.Z, literal.x, ; EG-NEXT: 32(4.484155e-44), 0(0.000000e+00) -; EG-NEXT: CNDE_INT * T0.Y, PS, PV.W, PV.Z, -; EG-NEXT: CNDE_INT T0.X, T1.W, T2.Z, 0.0, +; EG-NEXT: CNDE_INT * T0.Y, PS, PV.Z, PV.W, +; EG-NEXT: CNDE_INT T0.X, T1.W, T0.W, 0.0, ; EG-NEXT: LSHR * T1.X, KC0[2].Y, literal.x, ; EG-NEXT: 2(2.802597e-45), 0(0.000000e+00) %b_ptr = getelementptr i64, ptr addrspace(1) %in, i64 1 @@ -858,8 +858,8 @@ define amdgpu_kernel void @shl_v2i64(ptr addrspace(1) %out, ptr addrspace(1) %in ; EG: ; %bb.0: ; EG-NEXT: ALU 0, @10, KC0[CB0:0-32], KC1[] ; EG-NEXT: TEX 1 @6 -; EG-NEXT: ALU 23, @11, KC0[CB0:0-32], KC1[] -; EG-NEXT: MEM_RAT_CACHELESS STORE_RAW T2.XYZW, T0.X, 1 +; EG-NEXT: ALU 22, @11, KC0[CB0:0-32], KC1[] +; EG-NEXT: MEM_RAT_CACHELESS STORE_RAW T3.XYZW, T0.X, 1 ; EG-NEXT: CF_END ; EG-NEXT: PAD ; EG-NEXT: Fetch clause starting at 6: @@ -868,28 +868,27 @@ define amdgpu_kernel void @shl_v2i64(ptr addrspace(1) %out, ptr addrspace(1) %in ; EG-NEXT: ALU clause starting at 10: ; EG-NEXT: MOV * T0.X, KC0[2].Z, ; EG-NEXT: ALU clause starting at 11: -; EG-NEXT: AND_INT * T1.W, T1.Z, literal.x, -; EG-NEXT: 31(4.344025e-44), 0(0.000000e+00) -; EG-NEXT: LSHL T2.X, T0.Z, PV.W, -; EG-NEXT: AND_INT T1.Y, T1.Z, literal.x, BS:VEC_120/SCL_212 +; EG-NEXT: AND_INT T1.Y, T1.Z, literal.x, ; EG-NEXT: LSHR T2.Z, T0.W, 1, -; EG-NEXT: BIT_ALIGN_INT T0.W, T0.W, T0.Z, 1, BS:VEC_102/SCL_221 +; EG-NEXT: BIT_ALIGN_INT T0.W, T0.W, T0.Z, 1, ; EG-NEXT: NOT_INT * T1.W, T1.Z, -; EG-NEXT: 32(4.484155e-44), 0(0.000000e+00) -; EG-NEXT: BIT_ALIGN_INT T3.X, PV.Z, PV.W, PS, -; EG-NEXT: LSHR T2.Y, T0.Y, 1, -; EG-NEXT: NOT_INT T0.Z, T1.X, -; EG-NEXT: BIT_ALIGN_INT T0.W, T0.Y, T0.X, 1, -; EG-NEXT: AND_INT * T1.W, T1.X, literal.x, ; EG-NEXT: 31(4.344025e-44), 0(0.000000e+00) -; EG-NEXT: LSHL T0.Y, T0.X, PS, BS:VEC_120/SCL_212 -; EG-NEXT: AND_INT T1.Z, T1.X, literal.x, BS:VEC_201 -; EG-NEXT: BIT_ALIGN_INT T0.W, PV.Y, PV.W, PV.Z, -; EG-NEXT: CNDE_INT * T2.W, T1.Y, PV.X, T2.X, +; EG-NEXT: BIT_ALIGN_INT T0.W, PV.Z, PV.W, PS, +; EG-NEXT: LSHL * T1.W, T0.Z, PV.Y, +; EG-NEXT: AND_INT T2.X, T1.Z, literal.x, +; EG-NEXT: AND_INT T1.Y, T1.X, literal.y, +; EG-NEXT: LSHR T0.Z, T0.Y, 1, +; EG-NEXT: BIT_ALIGN_INT T2.W, T0.Y, T0.X, 1, +; EG-NEXT: NOT_INT * T3.W, T1.X, +; EG-NEXT: 32(4.484155e-44), 31(4.344025e-44) +; EG-NEXT: BIT_ALIGN_INT T0.Y, PV.Z, PV.W, PS, +; EG-NEXT: LSHL T0.Z, T0.X, PV.Y, +; EG-NEXT: AND_INT T2.W, T1.X, literal.x, BS:VEC_120/SCL_212 +; EG-NEXT: CNDE_INT * T3.W, PV.X, T0.W, T1.W, ; EG-NEXT: 32(4.484155e-44), 0(0.000000e+00) -; EG-NEXT: CNDE_INT T2.Y, PV.Z, PV.W, PV.Y, -; EG-NEXT: CNDE_INT * T2.Z, T1.Y, T2.X, 0.0, -; EG-NEXT: CNDE_INT T2.X, T1.Z, T0.Y, 0.0, +; EG-NEXT: CNDE_INT T3.Y, PV.W, PV.Y, PV.Z, +; EG-NEXT: CNDE_INT * T3.Z, T2.X, T1.W, 0.0, +; EG-NEXT: CNDE_INT T3.X, T2.W, T0.Z, 0.0, ; EG-NEXT: LSHR * T0.X, KC0[2].Y, literal.x, ; EG-NEXT: 2(2.802597e-45), 0(0.000000e+00) %b_ptr = getelementptr <2 x i64>, ptr addrspace(1) %in, i64 1 @@ -956,66 +955,65 @@ define amdgpu_kernel void @shl_v4i64(ptr addrspace(1) %out, ptr addrspace(1) %in ; EG: ; %bb.0: ; EG-NEXT: ALU 0, @14, KC0[CB0:0-32], KC1[] ; EG-NEXT: TEX 3 @6 -; EG-NEXT: ALU 48, @15, KC0[CB0:0-32], KC1[] -; EG-NEXT: MEM_RAT_CACHELESS STORE_RAW T2.XYZW, T0.X, 0 -; EG-NEXT: MEM_RAT_CACHELESS STORE_RAW T3.XYZW, T1.X, 1 +; EG-NEXT: ALU 47, @15, KC0[CB0:0-32], KC1[] +; EG-NEXT: MEM_RAT_CACHELESS STORE_RAW T1.XYZW, T2.X, 0 +; EG-NEXT: MEM_RAT_CACHELESS STORE_RAW T4.XYZW, T0.X, 1 ; EG-NEXT: CF_END ; EG-NEXT: Fetch clause starting at 6: -; EG-NEXT: VTX_READ_128 T1.XYZW, T0.X, 32, #1 -; EG-NEXT: VTX_READ_128 T2.XYZW, T0.X, 48, #1 -; EG-NEXT: VTX_READ_128 T3.XYZW, T0.X, 16, #1 -; EG-NEXT: VTX_READ_128 T0.XYZW, T0.X, 0, #1 +; EG-NEXT: VTX_READ_128 T1.XYZW, T0.X, 48, #1 +; EG-NEXT: VTX_READ_128 T2.XYZW, T0.X, 0, #1 +; EG-NEXT: VTX_READ_128 T3.XYZW, T0.X, 32, #1 +; EG-NEXT: VTX_READ_128 T0.XYZW, T0.X, 16, #1 ; EG-NEXT: ALU clause starting at 14: ; EG-NEXT: MOV * T0.X, KC0[2].Z, ; EG-NEXT: ALU clause starting at 15: -; EG-NEXT: AND_INT * T1.W, T1.Z, literal.x, +; EG-NEXT: AND_INT T4.Z, T1.Z, literal.x, +; EG-NEXT: LSHR T1.W, T0.W, 1, +; EG-NEXT: NOT_INT * T3.W, T1.Z, ; EG-NEXT: 31(4.344025e-44), 0(0.000000e+00) -; EG-NEXT: LSHL * T1.W, T0.Z, PV.W, +; EG-NEXT: BIT_ALIGN_INT T4.X, T0.W, T0.Z, 1, +; EG-NEXT: AND_INT T1.Y, T3.Z, literal.x, BS:VEC_201 +; EG-NEXT: LSHR T5.Z, T2.W, 1, BS:VEC_120/SCL_212 +; EG-NEXT: BIT_ALIGN_INT T0.W, T2.W, T2.Z, 1, BS:VEC_102/SCL_221 +; EG-NEXT: NOT_INT * T2.W, T3.Z, +; EG-NEXT: 31(4.344025e-44), 0(0.000000e+00) +; EG-NEXT: BIT_ALIGN_INT T3.Y, PV.Z, PV.W, PS, +; EG-NEXT: LSHL T2.Z, T2.Z, PV.Y, +; EG-NEXT: BIT_ALIGN_INT T0.W, T1.W, PV.X, T3.W, +; EG-NEXT: LSHL * T1.W, T0.Z, T4.Z, ; EG-NEXT: AND_INT T4.X, T1.Z, literal.x, -; EG-NEXT: LSHR T1.Y, T3.W, 1, -; EG-NEXT: NOT_INT T4.Z, T2.Z, BS:VEC_201 -; EG-NEXT: BIT_ALIGN_INT T2.W, T3.W, T3.Z, 1, -; EG-NEXT: AND_INT * T3.W, T2.Z, literal.y, +; EG-NEXT: AND_INT T1.Y, T1.X, literal.y, +; EG-NEXT: LSHR T0.Z, T0.Y, 1, +; EG-NEXT: BIT_ALIGN_INT T2.W, T0.Y, T0.X, 1, +; EG-NEXT: NOT_INT * T3.W, T1.X, ; EG-NEXT: 32(4.484155e-44), 31(4.344025e-44) -; EG-NEXT: LSHL T5.X, T3.Z, PS, -; EG-NEXT: AND_INT T2.Y, T2.Z, literal.x, BS:VEC_120/SCL_212 -; EG-NEXT: BIT_ALIGN_INT T2.Z, PV.Y, PV.W, PV.Z, -; EG-NEXT: LSHR T2.W, T3.Y, 1, -; EG-NEXT: NOT_INT * T3.W, T2.X, -; EG-NEXT: 32(4.484155e-44), 0(0.000000e+00) -; EG-NEXT: BIT_ALIGN_INT T6.X, T3.Y, T3.X, 1, -; EG-NEXT: AND_INT T1.Y, T2.X, literal.x, -; EG-NEXT: LSHR T3.Z, T0.W, 1, -; EG-NEXT: BIT_ALIGN_INT T0.W, T0.W, T0.Z, 1, -; EG-NEXT: NOT_INT * T4.W, T1.Z, -; EG-NEXT: 31(4.344025e-44), 0(0.000000e+00) -; EG-NEXT: BIT_ALIGN_INT T7.X, PV.Z, PV.W, PS, -; EG-NEXT: LSHL T1.Y, T3.X, PV.Y, BS:VEC_120/SCL_212 -; EG-NEXT: AND_INT T0.Z, T2.X, literal.x, BS:VEC_201 -; EG-NEXT: BIT_ALIGN_INT T0.W, T2.W, PV.X, T3.W, -; EG-NEXT: CNDE_INT * T3.W, T2.Y, T2.Z, T5.X, +; EG-NEXT: AND_INT T5.X, T3.Z, literal.x, +; EG-NEXT: BIT_ALIGN_INT T0.Y, PV.Z, PV.W, PS, +; EG-NEXT: LSHL T0.Z, T0.X, PV.Y, +; EG-NEXT: AND_INT T2.W, T1.X, literal.x, BS:VEC_120/SCL_212 +; EG-NEXT: CNDE_INT * T4.W, PV.X, T0.W, T1.W, ; EG-NEXT: 32(4.484155e-44), 0(0.000000e+00) -; EG-NEXT: LSHR T2.X, T0.Y, 1, -; EG-NEXT: CNDE_INT T3.Y, PV.Z, PV.W, PV.Y, -; EG-NEXT: NOT_INT T1.Z, T1.X, -; EG-NEXT: BIT_ALIGN_INT T0.W, T0.Y, T0.X, 1, -; EG-NEXT: AND_INT * T2.W, T1.X, literal.x, +; EG-NEXT: AND_INT T0.X, T3.X, literal.x, +; EG-NEXT: CNDE_INT T4.Y, PV.W, PV.Y, PV.Z, +; EG-NEXT: LSHR T1.Z, T2.Y, 1, +; EG-NEXT: BIT_ALIGN_INT T0.W, T2.Y, T2.X, 1, +; EG-NEXT: NOT_INT * T3.W, T3.X, ; EG-NEXT: 31(4.344025e-44), 0(0.000000e+00) -; EG-NEXT: LSHL T0.X, T0.X, PS, -; EG-NEXT: AND_INT T0.Y, T1.X, literal.x, BS:VEC_120/SCL_212 -; EG-NEXT: CNDE_INT T3.Z, T2.Y, T5.X, 0.0, BS:VEC_021/SCL_122 -; EG-NEXT: BIT_ALIGN_INT * T0.W, PV.X, PV.W, PV.Z, +; EG-NEXT: BIT_ALIGN_INT T1.X, PV.Z, PV.W, PS, +; EG-NEXT: LSHL T0.Y, T2.X, PV.X, +; EG-NEXT: CNDE_INT T4.Z, T4.X, T1.W, 0.0, BS:VEC_120/SCL_212 +; EG-NEXT: AND_INT * T0.W, T3.X, literal.x, BS:VEC_201 ; EG-NEXT: 32(4.484155e-44), 0(0.000000e+00) -; EG-NEXT: CNDE_INT * T2.W, T4.X, T7.X, T1.W, -; EG-NEXT: CNDE_INT T3.X, T0.Z, T1.Y, 0.0, -; EG-NEXT: CNDE_INT T2.Y, T0.Y, T0.W, T0.X, -; EG-NEXT: ADD_INT * T0.W, KC0[2].Y, literal.x, +; EG-NEXT: CNDE_INT * T1.W, T5.X, T3.Y, T2.Z, +; EG-NEXT: CNDE_INT T4.X, T2.W, T0.Z, 0.0, +; EG-NEXT: CNDE_INT T1.Y, T0.W, T1.X, T0.Y, BS:VEC_120/SCL_212 +; EG-NEXT: ADD_INT * T2.W, KC0[2].Y, literal.x, ; EG-NEXT: 16(2.242078e-44), 0(0.000000e+00) -; EG-NEXT: LSHR T1.X, PV.W, literal.x, -; EG-NEXT: CNDE_INT T2.Z, T4.X, T1.W, 0.0, -; EG-NEXT: CNDE_INT * T2.X, T0.Y, T0.X, 0.0, +; EG-NEXT: LSHR T0.X, PV.W, literal.x, +; EG-NEXT: CNDE_INT T1.Z, T5.X, T2.Z, 0.0, +; EG-NEXT: CNDE_INT * T1.X, T0.W, T0.Y, 0.0, ; EG-NEXT: 2(2.802597e-45), 0(0.000000e+00) -; EG-NEXT: LSHR * T0.X, KC0[2].Y, literal.x, +; EG-NEXT: LSHR * T2.X, KC0[2].Y, literal.x, ; EG-NEXT: 2(2.802597e-45), 0(0.000000e+00) %b_ptr = getelementptr <4 x i64>, ptr addrspace(1) %in, i64 1 %a = load <4 x i64>, ptr addrspace(1) %in @@ -1174,17 +1172,17 @@ define amdgpu_kernel void @s_shl_constant_i64(ptr addrspace(1) %out, i64 %a) { ; EG-NEXT: CF_END ; EG-NEXT: PAD ; EG-NEXT: ALU clause starting at 4: -; EG-NEXT: MOV T0.Z, literal.x, -; EG-NEXT: NOT_INT T0.W, KC0[2].W, -; EG-NEXT: AND_INT * T1.W, KC0[2].W, literal.y, -; EG-NEXT: -1(nan), 31(4.344025e-44) -; EG-NEXT: LSHL T1.Z, literal.x, PS, -; EG-NEXT: BIT_ALIGN_INT T0.W, literal.y, PV.Z, PV.W, +; EG-NEXT: AND_INT T0.Z, KC0[2].W, literal.x, +; EG-NEXT: MOV T0.W, literal.y, +; EG-NEXT: NOT_INT * T1.W, KC0[2].W, +; EG-NEXT: 31(4.344025e-44), -1(nan) +; EG-NEXT: BIT_ALIGN_INT T1.Z, literal.x, PV.W, PS, +; EG-NEXT: LSHL T0.W, literal.y, PV.Z, ; EG-NEXT: AND_INT * T1.W, KC0[2].W, literal.z, -; EG-NEXT: -1(nan), 32767(4.591635e-41) +; EG-NEXT: 32767(4.591635e-41), -1(nan) ; EG-NEXT: 32(4.484155e-44), 0(0.000000e+00) -; EG-NEXT: CNDE_INT * T0.Y, PS, PV.W, PV.Z, -; EG-NEXT: CNDE_INT T0.X, T1.W, T1.Z, 0.0, +; EG-NEXT: CNDE_INT * T0.Y, PS, PV.Z, PV.W, +; EG-NEXT: CNDE_INT T0.X, T1.W, T0.W, 0.0, ; EG-NEXT: LSHR * T1.X, KC0[2].Y, literal.x, ; EG-NEXT: 2(2.802597e-45), 0(0.000000e+00) %shl = shl i64 281474976710655, %a @@ -1425,15 +1423,15 @@ define amdgpu_kernel void @s_shl_inline_imm_64_i64(ptr addrspace(1) %out, ptr ad ; EG-NEXT: CF_END ; EG-NEXT: PAD ; EG-NEXT: ALU clause starting at 4: -; EG-NEXT: AND_INT T0.W, KC0[2].W, literal.x, -; EG-NEXT: NOT_INT * T1.W, KC0[2].W, +; EG-NEXT: NOT_INT T0.W, KC0[2].W, +; EG-NEXT: AND_INT * T1.W, KC0[2].W, literal.x, ; EG-NEXT: 31(4.344025e-44), 0(0.000000e+00) -; EG-NEXT: BIT_ALIGN_INT T0.Z, 0.0, literal.x, PS, -; EG-NEXT: AND_INT T1.W, KC0[2].W, literal.x, -; EG-NEXT: LSHL * T0.W, literal.y, PV.W, -; EG-NEXT: 32(4.484155e-44), 64(8.968310e-44) -; EG-NEXT: CNDE_INT * T0.Y, PV.W, PV.Z, PS, -; EG-NEXT: CNDE_INT T0.X, T1.W, T0.W, 0.0, +; EG-NEXT: LSHL T0.Z, literal.x, PS, +; EG-NEXT: BIT_ALIGN_INT T0.W, 0.0, literal.y, PV.W, +; EG-NEXT: AND_INT * T1.W, KC0[2].W, literal.y, +; EG-NEXT: 64(8.968310e-44), 32(4.484155e-44) +; EG-NEXT: CNDE_INT * T0.Y, PS, PV.W, PV.Z, +; EG-NEXT: CNDE_INT T0.X, T1.W, T0.Z, 0.0, ; EG-NEXT: LSHR * T1.X, KC0[2].Y, literal.x, ; EG-NEXT: 2(2.802597e-45), 0(0.000000e+00) %shl = shl i64 64, %a @@ -1905,16 +1903,16 @@ define amdgpu_kernel void @s_shl_inline_imm_f32_4_0_i64(ptr addrspace(1) %out, p ; EG-NEXT: CF_END ; EG-NEXT: PAD ; EG-NEXT: ALU clause starting at 4: -; EG-NEXT: AND_INT T0.W, KC0[2].W, literal.x, -; EG-NEXT: NOT_INT * T1.W, KC0[2].W, +; EG-NEXT: NOT_INT T0.W, KC0[2].W, +; EG-NEXT: AND_INT * T1.W, KC0[2].W, literal.x, ; EG-NEXT: 31(4.344025e-44), 0(0.000000e+00) -; EG-NEXT: BIT_ALIGN_INT T0.Z, 0.0, literal.x, PS, -; EG-NEXT: AND_INT T1.W, KC0[2].W, literal.y, -; EG-NEXT: LSHL * T0.W, literal.z, PV.W, -; EG-NEXT: 541065216(1.626303e-19), 32(4.484155e-44) -; EG-NEXT: 1082130432(4.000000e+00), 0(0.000000e+00) -; EG-NEXT: CNDE_INT * T0.Y, PV.W, PV.Z, PS, -; EG-NEXT: CNDE_INT T0.X, T1.W, T0.W, 0.0, +; EG-NEXT: LSHL T0.Z, literal.x, PS, +; EG-NEXT: BIT_ALIGN_INT T0.W, 0.0, literal.y, PV.W, +; EG-NEXT: AND_INT * T1.W, KC0[2].W, literal.z, +; EG-NEXT: 1082130432(4.000000e+00), 541065216(1.626303e-19) +; EG-NEXT: 32(4.484155e-44), 0(0.000000e+00) +; EG-NEXT: CNDE_INT * T0.Y, PS, PV.W, PV.Z, +; EG-NEXT: CNDE_INT T0.X, T1.W, T0.Z, 0.0, ; EG-NEXT: LSHR * T1.X, KC0[2].Y, literal.x, ; EG-NEXT: 2(2.802597e-45), 0(0.000000e+00) %shl = shl i64 1082130432, %a @@ -1961,17 +1959,17 @@ define amdgpu_kernel void @s_shl_inline_imm_f32_neg_4_0_i64(ptr addrspace(1) %ou ; EG-NEXT: CF_END ; EG-NEXT: PAD ; EG-NEXT: ALU clause starting at 4: -; EG-NEXT: MOV T0.Z, literal.x, -; EG-NEXT: NOT_INT T0.W, KC0[2].W, -; EG-NEXT: AND_INT * T1.W, KC0[2].W, literal.y, -; EG-NEXT: -532676608(-5.534023e+19), 31(4.344025e-44) -; EG-NEXT: LSHL T1.Z, literal.x, PS, -; EG-NEXT: BIT_ALIGN_INT T0.W, literal.y, PV.Z, PV.W, +; EG-NEXT: AND_INT T0.Z, KC0[2].W, literal.x, +; EG-NEXT: MOV T0.W, literal.y, +; EG-NEXT: NOT_INT * T1.W, KC0[2].W, +; EG-NEXT: 31(4.344025e-44), -532676608(-5.534023e+19) +; EG-NEXT: BIT_ALIGN_INT T1.Z, literal.x, PV.W, PS, +; EG-NEXT: LSHL T0.W, literal.y, PV.Z, ; EG-NEXT: AND_INT * T1.W, KC0[2].W, literal.z, -; EG-NEXT: -1065353216(-4.000000e+00), 2147483647(nan) +; EG-NEXT: 2147483647(nan), -1065353216(-4.000000e+00) ; EG-NEXT: 32(4.484155e-44), 0(0.000000e+00) -; EG-NEXT: CNDE_INT * T0.Y, PS, PV.W, PV.Z, -; EG-NEXT: CNDE_INT T0.X, T1.W, T1.Z, 0.0, +; EG-NEXT: CNDE_INT * T0.Y, PS, PV.Z, PV.W, +; EG-NEXT: CNDE_INT T0.X, T1.W, T0.W, 0.0, ; EG-NEXT: LSHR * T1.X, KC0[2].Y, literal.x, ; EG-NEXT: 2(2.802597e-45), 0(0.000000e+00) %shl = shl i64 -1065353216, %a -- GitLab From 1015f51dd94a6154df7183004743e1a86e566858 Mon Sep 17 00:00:00 2001 From: Sander de Smalen Date: Wed, 22 May 2024 07:58:54 +0100 Subject: [PATCH 078/452] [AArch64] NFC: Rename -force-streaming-compatible-sve to -force-streaming-compatible (#92774) The behaviour of the flag should be equivalent to __arm_streaming_compatible. At the moment, the name suggests that '-force-streaming-compatible-sve' on its own (i.e. without specifying `+sve`) enables the compiler to use the streaming-compatible subset of SVE instructions, but the semantics merely are that the function can be called with either PSTATE.SM=0 or PSTATE.SM=1. --- llvm/lib/Target/AArch64/AArch64Subtarget.cpp | 27 +++---------------- llvm/lib/Target/AArch64/AArch64Subtarget.h | 21 +++++++++------ .../Target/AArch64/AArch64TargetMachine.cpp | 27 ++++++++++--------- llvm/test/Analysis/CostModel/AArch64/cast.ll | 2 +- .../sve-fixed-length-vector-shuffle-tbl.ll | 8 +++--- .../CodeGen/AArch64/sve-fp-reduce-fadda.ll | 2 +- ...streaming-mode-fixed-length-and-combine.ll | 4 +-- ...treaming-mode-fixed-length-bit-counting.ll | 4 +-- ...sve-streaming-mode-fixed-length-bitcast.ll | 4 +-- ...e-streaming-mode-fixed-length-bitselect.ll | 4 +-- ...treaming-mode-fixed-length-build-vector.ll | 4 +-- .../sve-streaming-mode-fixed-length-concat.ll | 4 +-- ...e-streaming-mode-fixed-length-ext-loads.ll | 4 +-- ...ing-mode-fixed-length-extract-subvector.ll | 4 +-- ...ng-mode-fixed-length-extract-vector-elt.ll | 4 +-- ...e-streaming-mode-fixed-length-fcopysign.ll | 6 ++--- ...ve-streaming-mode-fixed-length-fp-arith.ll | 4 +-- ...streaming-mode-fixed-length-fp-compares.ll | 4 +-- ...-streaming-mode-fixed-length-fp-convert.ll | 4 +-- ...aming-mode-fixed-length-fp-extend-trunc.ll | 4 +-- .../sve-streaming-mode-fixed-length-fp-fma.ll | 2 +- ...e-streaming-mode-fixed-length-fp-minmax.ll | 4 +-- ...eaming-mode-fixed-length-fp-reduce-fa64.ll | 4 +-- ...e-streaming-mode-fixed-length-fp-reduce.ll | 2 +- ...streaming-mode-fixed-length-fp-rounding.ll | 4 +-- ...e-streaming-mode-fixed-length-fp-select.ll | 4 +-- ...e-streaming-mode-fixed-length-fp-to-int.ll | 2 +- ...-streaming-mode-fixed-length-fp-vselect.ll | 4 +-- ...ing-mode-fixed-length-insert-vector-elt.ll | 2 +- ...e-streaming-mode-fixed-length-int-arith.ll | 6 ++--- ...treaming-mode-fixed-length-int-compares.ll | 4 +-- ...sve-streaming-mode-fixed-length-int-div.ll | 6 ++--- ...streaming-mode-fixed-length-int-extends.ll | 6 ++--- ...eaming-mode-fixed-length-int-immediates.ll | 4 +-- ...sve-streaming-mode-fixed-length-int-log.ll | 4 +-- ...-streaming-mode-fixed-length-int-minmax.ll | 4 +-- ...ing-mode-fixed-length-int-mla-neon-fa64.ll | 4 +-- ...ve-streaming-mode-fixed-length-int-mulh.ll | 6 ++--- ...-streaming-mode-fixed-length-int-reduce.ll | 4 +-- ...sve-streaming-mode-fixed-length-int-rem.ll | 4 +-- ...-streaming-mode-fixed-length-int-select.ll | 4 +-- ...-streaming-mode-fixed-length-int-shifts.ll | 4 +-- ...e-streaming-mode-fixed-length-int-to-fp.ll | 2 +- ...streaming-mode-fixed-length-int-vselect.ll | 4 +-- ...-streaming-mode-fixed-length-ld2-alloca.ll | 6 ++--- ...reaming-mode-fixed-length-limit-duplane.ll | 4 +-- .../sve-streaming-mode-fixed-length-loads.ll | 4 +-- ...-streaming-mode-fixed-length-log-reduce.ll | 4 +-- ...streaming-mode-fixed-length-masked-load.ll | 2 +- ...treaming-mode-fixed-length-masked-store.ll | 2 +- ...eaming-mode-fixed-length-optimize-ptrue.ll | 4 +-- ...streaming-mode-fixed-length-permute-rev.ll | 4 +-- ...g-mode-fixed-length-permute-zip-uzp-trn.ll | 4 +-- .../sve-streaming-mode-fixed-length-ptest.ll | 4 +-- ...e-streaming-mode-fixed-length-reshuffle.ll | 4 +-- .../sve-streaming-mode-fixed-length-rev.ll | 4 +-- ...e-streaming-mode-fixed-length-sdiv-pow2.ll | 4 +-- ...sve-streaming-mode-fixed-length-shuffle.ll | 6 ++--- ...treaming-mode-fixed-length-splat-vector.ll | 2 +- .../sve-streaming-mode-fixed-length-stores.ll | 4 +-- ...e-streaming-mode-fixed-length-subvector.ll | 4 +-- ...treaming-mode-fixed-length-trunc-stores.ll | 4 +-- .../sve-streaming-mode-fixed-length-trunc.ll | 4 +-- ...eaming-mode-fixed-length-vector-shuffle.ll | 4 +-- .../sve-streaming-mode-test-register-mov.ll | 4 +-- .../AArch64/fixed-deinterleave-intrinsics.ll | 4 +-- ...ng-compatible-sve-no-maximize-bandwidth.ll | 2 +- ...compatible-expand-masked-gather-scatter.ll | 2 +- 68 files changed, 158 insertions(+), 171 deletions(-) diff --git a/llvm/lib/Target/AArch64/AArch64Subtarget.cpp b/llvm/lib/Target/AArch64/AArch64Subtarget.cpp index 5d185fcaefc4..8bc26eeef34d 100644 --- a/llvm/lib/Target/AArch64/AArch64Subtarget.cpp +++ b/llvm/lib/Target/AArch64/AArch64Subtarget.cpp @@ -64,12 +64,6 @@ ReservedRegsForRA("reserve-regs-for-regalloc", cl::desc("Reserve physical " "Should only be used for testing register allocator."), cl::CommaSeparated, cl::Hidden); -static cl::opt ForceStreamingCompatibleSVE( - "force-streaming-compatible-sve", - cl::desc( - "Force the use of streaming-compatible SVE code for all functions"), - cl::Hidden); - static cl::opt AuthenticatedLRCheckMethod("aarch64-authenticated-lr-check-method", cl::Hidden, @@ -316,15 +310,14 @@ AArch64Subtarget::AArch64Subtarget(const Triple &TT, StringRef CPU, const TargetMachine &TM, bool LittleEndian, unsigned MinSVEVectorSizeInBitsOverride, unsigned MaxSVEVectorSizeInBitsOverride, - bool StreamingSVEMode, - bool StreamingCompatibleSVEMode, + bool IsStreaming, bool IsStreamingCompatible, bool HasMinSize) : AArch64GenSubtargetInfo(TT, CPU, TuneCPU, FS), ReserveXRegister(AArch64::GPR64commonRegClass.getNumRegs()), ReserveXRegisterForRA(AArch64::GPR64commonRegClass.getNumRegs()), CustomCallSavedXRegs(AArch64::GPR64commonRegClass.getNumRegs()), - IsLittle(LittleEndian), StreamingSVEMode(StreamingSVEMode), - StreamingCompatibleSVEMode(StreamingCompatibleSVEMode), + IsLittle(LittleEndian), IsStreaming(IsStreaming), + IsStreamingCompatible(IsStreamingCompatible), MinSVEVectorSizeInBits(MinSVEVectorSizeInBitsOverride), MaxSVEVectorSizeInBits(MaxSVEVectorSizeInBitsOverride), TargetTriple(TT), InstrInfo(initializeSubtargetDependencies(FS, CPU, TuneCPU, HasMinSize)), @@ -547,20 +540,6 @@ void AArch64Subtarget::mirFileLoaded(MachineFunction &MF) const { bool AArch64Subtarget::useAA() const { return UseAA; } -bool AArch64Subtarget::isStreamingCompatible() const { - return StreamingCompatibleSVEMode || ForceStreamingCompatibleSVE; -} - -bool AArch64Subtarget::isNeonAvailable() const { - return hasNEON() && - (hasSMEFA64() || (!isStreaming() && !isStreamingCompatible())); -} - -bool AArch64Subtarget::isSVEAvailable() const { - return hasSVE() && - (hasSMEFA64() || (!isStreaming() && !isStreamingCompatible())); -} - // If return address signing is enabled, tail calls are emitted as follows: // // ``` diff --git a/llvm/lib/Target/AArch64/AArch64Subtarget.h b/llvm/lib/Target/AArch64/AArch64Subtarget.h index 3f3eefc4f680..7ef7a89b5749 100644 --- a/llvm/lib/Target/AArch64/AArch64Subtarget.h +++ b/llvm/lib/Target/AArch64/AArch64Subtarget.h @@ -79,8 +79,8 @@ protected: bool IsLittle; - bool StreamingSVEMode; - bool StreamingCompatibleSVEMode; + bool IsStreaming; + bool IsStreamingCompatible; unsigned MinSVEVectorSizeInBits; unsigned MaxSVEVectorSizeInBits; unsigned VScaleForTuning = 2; @@ -120,8 +120,7 @@ public: StringRef FS, const TargetMachine &TM, bool LittleEndian, unsigned MinSVEVectorSizeInBitsOverride = 0, unsigned MaxSVEVectorSizeInBitsOverride = 0, - bool StreamingSVEMode = false, - bool StreamingCompatibleSVEMode = false, + bool IsStreaming = false, bool IsStreamingCompatible = false, bool HasMinSize = false); // Getters for SubtargetFeatures defined in tablegen @@ -165,20 +164,26 @@ public: bool isXRaySupported() const override { return true; } /// Returns true if the function has a streaming body. - bool isStreaming() const { return StreamingSVEMode; } + bool isStreaming() const { return IsStreaming; } /// Returns true if the function has a streaming-compatible body. - bool isStreamingCompatible() const; + bool isStreamingCompatible() const { return IsStreamingCompatible; } /// Returns true if the target has NEON and the function at runtime is known /// to have NEON enabled (e.g. the function is known not to be in streaming-SVE /// mode, which disables NEON instructions). - bool isNeonAvailable() const; + bool isNeonAvailable() const { + return hasNEON() && + (hasSMEFA64() || (!isStreaming() && !isStreamingCompatible())); + } /// Returns true if the target has SVE and can use the full range of SVE /// instructions, for example because it knows the function is known not to be /// in streaming-SVE mode or when the target has FEAT_FA64 enabled. - bool isSVEAvailable() const; + bool isSVEAvailable() const { + return hasSVE() && + (hasSMEFA64() || (!isStreaming() && !isStreamingCompatible())); + } unsigned getMinVectorRegisterBitWidth() const { // Don't assume any minimum vector size when PSTATE.SM may not be 0, because diff --git a/llvm/lib/Target/AArch64/AArch64TargetMachine.cpp b/llvm/lib/Target/AArch64/AArch64TargetMachine.cpp index df802cf42526..945ab5cf1f30 100644 --- a/llvm/lib/Target/AArch64/AArch64TargetMachine.cpp +++ b/llvm/lib/Target/AArch64/AArch64TargetMachine.cpp @@ -187,6 +187,11 @@ static cl::opt SVEVectorBitsMinOpt( "with zero meaning no minimum size is assumed."), cl::init(0), cl::Hidden); +static cl::opt ForceStreamingCompatible( + "force-streaming-compatible", + cl::desc("Force the use of streaming-compatible code for all functions"), + cl::init(false), cl::Hidden); + extern cl::opt EnableHomogeneousPrologEpilog; static cl::opt EnableGISelLoadStoreOptPreLegal( @@ -408,10 +413,11 @@ AArch64TargetMachine::getSubtargetImpl(const Function &F) const { StringRef FS = FSAttr.isValid() ? FSAttr.getValueAsString() : TargetFS; bool HasMinSize = F.hasMinSize(); - bool StreamingSVEMode = F.hasFnAttribute("aarch64_pstate_sm_enabled") || - F.hasFnAttribute("aarch64_pstate_sm_body"); - bool StreamingCompatibleSVEMode = - F.hasFnAttribute("aarch64_pstate_sm_compatible"); + bool IsStreaming = F.hasFnAttribute("aarch64_pstate_sm_enabled") || + F.hasFnAttribute("aarch64_pstate_sm_body"); + bool IsStreamingCompatible = + F.hasFnAttribute("aarch64_pstate_sm_compatible") || + ForceStreamingCompatible; unsigned MinSVEVectorSize = 0; unsigned MaxSVEVectorSize = 0; @@ -439,10 +445,9 @@ AArch64TargetMachine::getSubtargetImpl(const Function &F) const { SmallString<512> Key; raw_svector_ostream(Key) << "SVEMin" << MinSVEVectorSize << "SVEMax" - << MaxSVEVectorSize - << "StreamingSVEMode=" << StreamingSVEMode - << "StreamingCompatibleSVEMode=" - << StreamingCompatibleSVEMode << CPU << TuneCPU << FS + << MaxSVEVectorSize << "IsStreaming=" << IsStreaming + << "IsStreamingCompatible=" << IsStreamingCompatible + << CPU << TuneCPU << FS << "HasMinSize=" << HasMinSize; auto &I = SubtargetMap[Key]; @@ -453,12 +458,10 @@ AArch64TargetMachine::getSubtargetImpl(const Function &F) const { resetTargetOptions(F); I = std::make_unique( TargetTriple, CPU, TuneCPU, FS, *this, isLittle, MinSVEVectorSize, - MaxSVEVectorSize, StreamingSVEMode, StreamingCompatibleSVEMode, - HasMinSize); + MaxSVEVectorSize, IsStreaming, IsStreamingCompatible, HasMinSize); } - assert((!StreamingSVEMode || I->hasSME()) && - "Expected SME to be available"); + assert((!IsStreaming || I->hasSME()) && "Expected SME to be available"); return I.get(); } diff --git a/llvm/test/Analysis/CostModel/AArch64/cast.ll b/llvm/test/Analysis/CostModel/AArch64/cast.ll index 0cd444f84985..fa778864ae97 100644 --- a/llvm/test/Analysis/CostModel/AArch64/cast.ll +++ b/llvm/test/Analysis/CostModel/AArch64/cast.ll @@ -1,6 +1,6 @@ ; NOTE: Assertions have been autogenerated by utils/update_analyze_test_checks.py ; RUN: opt -passes="print" 2>&1 -disable-output -mtriple=aarch64 %s | FileCheck --check-prefixes=CHECK,CHECK-NOFP16 %s -; RUN: opt -passes="print" 2>&1 -disable-output -mtriple=aarch64 -mattr=+sve -force-streaming-compatible-sve %s | FileCheck --check-prefixes=SVE,SVE128-NO-NEON %s +; RUN: opt -passes="print" 2>&1 -disable-output -mtriple=aarch64 -mattr=+sve -force-streaming-compatible %s | FileCheck --check-prefixes=SVE,SVE128-NO-NEON %s ; RUN: opt -passes="print" 2>&1 -disable-output -mtriple=aarch64 -mattr=+fullfp16 %s | FileCheck --check-prefixes=CHECK,CHECK-FP16 %s ; RUN: opt -passes="print" 2>&1 -disable-output -mtriple=aarch64 -mattr=+sve -aarch64-sve-vector-bits-min=256 %s | FileCheck --check-prefixes=SVE,FIXED-MIN-256 %s ; RUN: opt -passes="print" 2>&1 -disable-output -mtriple=aarch64 -mattr=+sve -aarch64-sve-vector-bits-min=2048 %s | FileCheck --check-prefixes=SVE,FIXED-MIN-2048 %s diff --git a/llvm/test/CodeGen/AArch64/sve-fixed-length-vector-shuffle-tbl.ll b/llvm/test/CodeGen/AArch64/sve-fixed-length-vector-shuffle-tbl.ll index 28094c7b68e7..276f23703df3 100644 --- a/llvm/test/CodeGen/AArch64/sve-fixed-length-vector-shuffle-tbl.ll +++ b/llvm/test/CodeGen/AArch64/sve-fixed-length-vector-shuffle-tbl.ll @@ -1,8 +1,8 @@ ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py -; RUN: llc -mattr=+sve2 -force-streaming-compatible-sve -aarch64-sve-vector-bits-min=128 -aarch64-sve-vector-bits-max=128 < %s | FileCheck %s -check-prefixes=CHECK,SVE2_128 -; RUN: llc -mattr=+sve2 -force-streaming-compatible-sve -aarch64-sve-vector-bits-min=128 < %s | FileCheck %s -check-prefixes=CHECK,SVE2_128_NOMAX -; RUN: llc -mattr=+sve2 -force-streaming-compatible-sve < %s | FileCheck %s -check-prefixes=CHECK,SVE2_NOMIN_NOMAX -; RUN: llc -mattr=+sve2 -force-streaming-compatible-sve -aarch64-sve-vector-bits-min=256 < %s | FileCheck %s -check-prefixes=CHECK,SVE2_MIN_256_NOMAX +; RUN: llc -mattr=+sve2 -force-streaming-compatible -aarch64-sve-vector-bits-min=128 -aarch64-sve-vector-bits-max=128 < %s | FileCheck %s -check-prefixes=CHECK,SVE2_128 +; RUN: llc -mattr=+sve2 -force-streaming-compatible -aarch64-sve-vector-bits-min=128 < %s | FileCheck %s -check-prefixes=CHECK,SVE2_128_NOMAX +; RUN: llc -mattr=+sve2 -force-streaming-compatible < %s | FileCheck %s -check-prefixes=CHECK,SVE2_NOMIN_NOMAX +; RUN: llc -mattr=+sve2 -force-streaming-compatible -aarch64-sve-vector-bits-min=256 < %s | FileCheck %s -check-prefixes=CHECK,SVE2_MIN_256_NOMAX target triple = "aarch64-unknown-linux-gnu" diff --git a/llvm/test/CodeGen/AArch64/sve-fp-reduce-fadda.ll b/llvm/test/CodeGen/AArch64/sve-fp-reduce-fadda.ll index 1a2ab8d4253a..b0b6a6a530dd 100644 --- a/llvm/test/CodeGen/AArch64/sve-fp-reduce-fadda.ll +++ b/llvm/test/CodeGen/AArch64/sve-fp-reduce-fadda.ll @@ -2,7 +2,7 @@ ; RUN: llc -mattr=+sve < %s | FileCheck %s ; Streaming-compatible SVE doesn't include FADDA, so this shouldn't compile! -; RUN: not --crash llc -mattr=+sve -force-streaming-compatible-sve < %s +; RUN: not --crash llc -mattr=+sve -force-streaming-compatible < %s target triple = "aarch64-linux-gnu" diff --git a/llvm/test/CodeGen/AArch64/sve-streaming-mode-fixed-length-and-combine.ll b/llvm/test/CodeGen/AArch64/sve-streaming-mode-fixed-length-and-combine.ll index d81f725eaefc..e843537c10a3 100644 --- a/llvm/test/CodeGen/AArch64/sve-streaming-mode-fixed-length-and-combine.ll +++ b/llvm/test/CodeGen/AArch64/sve-streaming-mode-fixed-length-and-combine.ll @@ -1,6 +1,6 @@ ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py -; RUN: llc -mattr=+sve -force-streaming-compatible-sve < %s | FileCheck %s -; RUN: llc -mattr=+sme -force-streaming-compatible-sve < %s | FileCheck %s +; RUN: llc -mattr=+sve -force-streaming-compatible < %s | FileCheck %s +; RUN: llc -mattr=+sme -force-streaming-compatible < %s | FileCheck %s target triple = "aarch64-unknown-linux-gnu" diff --git a/llvm/test/CodeGen/AArch64/sve-streaming-mode-fixed-length-bit-counting.ll b/llvm/test/CodeGen/AArch64/sve-streaming-mode-fixed-length-bit-counting.ll index d547f99a0230..aa42d5c2a8c1 100644 --- a/llvm/test/CodeGen/AArch64/sve-streaming-mode-fixed-length-bit-counting.ll +++ b/llvm/test/CodeGen/AArch64/sve-streaming-mode-fixed-length-bit-counting.ll @@ -1,6 +1,6 @@ ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py -; RUN: llc -mattr=+sve -force-streaming-compatible-sve < %s | FileCheck %s -; RUN: llc -mattr=+sme -force-streaming-compatible-sve < %s | FileCheck %s +; RUN: llc -mattr=+sve -force-streaming-compatible < %s | FileCheck %s +; RUN: llc -mattr=+sme -force-streaming-compatible < %s | FileCheck %s target triple = "aarch64-unknown-linux-gnu" diff --git a/llvm/test/CodeGen/AArch64/sve-streaming-mode-fixed-length-bitcast.ll b/llvm/test/CodeGen/AArch64/sve-streaming-mode-fixed-length-bitcast.ll index e3cc74f766ee..260ad16581f1 100644 --- a/llvm/test/CodeGen/AArch64/sve-streaming-mode-fixed-length-bitcast.ll +++ b/llvm/test/CodeGen/AArch64/sve-streaming-mode-fixed-length-bitcast.ll @@ -1,6 +1,6 @@ ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py -; RUN: llc -mattr=+sve -force-streaming-compatible-sve < %s | FileCheck %s -; RUN: llc -mattr=+sme -force-streaming-compatible-sve < %s | FileCheck %s +; RUN: llc -mattr=+sve -force-streaming-compatible < %s | FileCheck %s +; RUN: llc -mattr=+sme -force-streaming-compatible < %s | FileCheck %s target triple = "aarch64-unknown-linux-gnu" diff --git a/llvm/test/CodeGen/AArch64/sve-streaming-mode-fixed-length-bitselect.ll b/llvm/test/CodeGen/AArch64/sve-streaming-mode-fixed-length-bitselect.ll index 74a4aab15597..9a07bd8bd5ac 100644 --- a/llvm/test/CodeGen/AArch64/sve-streaming-mode-fixed-length-bitselect.ll +++ b/llvm/test/CodeGen/AArch64/sve-streaming-mode-fixed-length-bitselect.ll @@ -1,6 +1,6 @@ ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py -; RUN: llc -mattr=+sve -force-streaming-compatible-sve < %s | FileCheck %s -; RUN: llc -mattr=+sme -force-streaming-compatible-sve < %s | FileCheck %s +; RUN: llc -mattr=+sve -force-streaming-compatible < %s | FileCheck %s +; RUN: llc -mattr=+sme -force-streaming-compatible < %s | FileCheck %s target triple = "aarch64" diff --git a/llvm/test/CodeGen/AArch64/sve-streaming-mode-fixed-length-build-vector.ll b/llvm/test/CodeGen/AArch64/sve-streaming-mode-fixed-length-build-vector.ll index 0c490a662a79..aec434b4819d 100644 --- a/llvm/test/CodeGen/AArch64/sve-streaming-mode-fixed-length-build-vector.ll +++ b/llvm/test/CodeGen/AArch64/sve-streaming-mode-fixed-length-build-vector.ll @@ -1,6 +1,6 @@ ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py -; RUN: llc -mattr=+sve -force-streaming-compatible-sve < %s | FileCheck %s -; RUN: llc -mattr=+sme -force-streaming-compatible-sve < %s | FileCheck %s +; RUN: llc -mattr=+sve -force-streaming-compatible < %s | FileCheck %s +; RUN: llc -mattr=+sme -force-streaming-compatible < %s | FileCheck %s target triple = "aarch64-unknown-linux-gnu" diff --git a/llvm/test/CodeGen/AArch64/sve-streaming-mode-fixed-length-concat.ll b/llvm/test/CodeGen/AArch64/sve-streaming-mode-fixed-length-concat.ll index 86494c4be501..82e75d6efda3 100644 --- a/llvm/test/CodeGen/AArch64/sve-streaming-mode-fixed-length-concat.ll +++ b/llvm/test/CodeGen/AArch64/sve-streaming-mode-fixed-length-concat.ll @@ -1,6 +1,6 @@ ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py -; RUN: llc -mattr=+sve -force-streaming-compatible-sve < %s | FileCheck %s -; RUN: llc -mattr=+sme -force-streaming-compatible-sve < %s | FileCheck %s +; RUN: llc -mattr=+sve -force-streaming-compatible < %s | FileCheck %s +; RUN: llc -mattr=+sme -force-streaming-compatible < %s | FileCheck %s target triple = "aarch64-unknown-linux-gnu" diff --git a/llvm/test/CodeGen/AArch64/sve-streaming-mode-fixed-length-ext-loads.ll b/llvm/test/CodeGen/AArch64/sve-streaming-mode-fixed-length-ext-loads.ll index 0aefba2d4c6a..040e5861e981 100644 --- a/llvm/test/CodeGen/AArch64/sve-streaming-mode-fixed-length-ext-loads.ll +++ b/llvm/test/CodeGen/AArch64/sve-streaming-mode-fixed-length-ext-loads.ll @@ -1,6 +1,6 @@ ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py -; RUN: llc -mattr=+sve -force-streaming-compatible-sve < %s | FileCheck %s -; RUN: llc -mattr=+sme -force-streaming-compatible-sve < %s | FileCheck %s +; RUN: llc -mattr=+sve -force-streaming-compatible < %s | FileCheck %s +; RUN: llc -mattr=+sme -force-streaming-compatible < %s | FileCheck %s target triple = "aarch64-unknown-linux-gnu" diff --git a/llvm/test/CodeGen/AArch64/sve-streaming-mode-fixed-length-extract-subvector.ll b/llvm/test/CodeGen/AArch64/sve-streaming-mode-fixed-length-extract-subvector.ll index 25ecd7a8d7e3..45a804becbc5 100644 --- a/llvm/test/CodeGen/AArch64/sve-streaming-mode-fixed-length-extract-subvector.ll +++ b/llvm/test/CodeGen/AArch64/sve-streaming-mode-fixed-length-extract-subvector.ll @@ -1,6 +1,6 @@ ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py -; RUN: llc -mattr=+sve -force-streaming-compatible-sve < %s | FileCheck %s -; RUN: llc -mattr=+sme -force-streaming-compatible-sve < %s | FileCheck %s +; RUN: llc -mattr=+sve -force-streaming-compatible < %s | FileCheck %s +; RUN: llc -mattr=+sme -force-streaming-compatible < %s | FileCheck %s target triple = "aarch64-unknown-linux-gnu" diff --git a/llvm/test/CodeGen/AArch64/sve-streaming-mode-fixed-length-extract-vector-elt.ll b/llvm/test/CodeGen/AArch64/sve-streaming-mode-fixed-length-extract-vector-elt.ll index a752e119b2fb..9c3b5e14289d 100644 --- a/llvm/test/CodeGen/AArch64/sve-streaming-mode-fixed-length-extract-vector-elt.ll +++ b/llvm/test/CodeGen/AArch64/sve-streaming-mode-fixed-length-extract-vector-elt.ll @@ -1,6 +1,6 @@ ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py -; RUN: llc -mattr=+sve -force-streaming-compatible-sve < %s | FileCheck %s -; RUN: llc -mattr=+sme -force-streaming-compatible-sve < %s | FileCheck %s +; RUN: llc -mattr=+sve -force-streaming-compatible < %s | FileCheck %s +; RUN: llc -mattr=+sme -force-streaming-compatible < %s | FileCheck %s target triple = "aarch64-unknown-linux-gnu" diff --git a/llvm/test/CodeGen/AArch64/sve-streaming-mode-fixed-length-fcopysign.ll b/llvm/test/CodeGen/AArch64/sve-streaming-mode-fixed-length-fcopysign.ll index f017eead92cf..21ce689f68e2 100644 --- a/llvm/test/CodeGen/AArch64/sve-streaming-mode-fixed-length-fcopysign.ll +++ b/llvm/test/CodeGen/AArch64/sve-streaming-mode-fixed-length-fcopysign.ll @@ -1,7 +1,7 @@ ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py -; RUN: llc -mattr=+sve -force-streaming-compatible-sve < %s | FileCheck %s --check-prefixes=CHECK,SVE -; RUN: llc -mattr=+sve2 -force-streaming-compatible-sve < %s | FileCheck %s --check-prefixes=CHECK,SVE2 -; RUN: llc -mattr=+sme -force-streaming-compatible-sve < %s | FileCheck %s --check-prefixes=CHECK,SVE2 +; RUN: llc -mattr=+sve -force-streaming-compatible < %s | FileCheck %s --check-prefixes=CHECK,SVE +; RUN: llc -mattr=+sve2 -force-streaming-compatible < %s | FileCheck %s --check-prefixes=CHECK,SVE2 +; RUN: llc -mattr=+sme -force-streaming-compatible < %s | FileCheck %s --check-prefixes=CHECK,SVE2 target datalayout = "e-m:o-i64:64-i128:128-n32:64-S128" diff --git a/llvm/test/CodeGen/AArch64/sve-streaming-mode-fixed-length-fp-arith.ll b/llvm/test/CodeGen/AArch64/sve-streaming-mode-fixed-length-fp-arith.ll index c2d6ed4e9ccf..b0a82e699939 100644 --- a/llvm/test/CodeGen/AArch64/sve-streaming-mode-fixed-length-fp-arith.ll +++ b/llvm/test/CodeGen/AArch64/sve-streaming-mode-fixed-length-fp-arith.ll @@ -1,6 +1,6 @@ ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py -; RUN: llc -mattr=+sve -force-streaming-compatible-sve < %s | FileCheck %s -; RUN: llc -mattr=+sme -force-streaming-compatible-sve < %s | FileCheck %s +; RUN: llc -mattr=+sve -force-streaming-compatible < %s | FileCheck %s +; RUN: llc -mattr=+sme -force-streaming-compatible < %s | FileCheck %s target triple = "aarch64-unknown-linux-gnu" diff --git a/llvm/test/CodeGen/AArch64/sve-streaming-mode-fixed-length-fp-compares.ll b/llvm/test/CodeGen/AArch64/sve-streaming-mode-fixed-length-fp-compares.ll index 465cc179a3b9..cbd0ad66fba7 100644 --- a/llvm/test/CodeGen/AArch64/sve-streaming-mode-fixed-length-fp-compares.ll +++ b/llvm/test/CodeGen/AArch64/sve-streaming-mode-fixed-length-fp-compares.ll @@ -1,6 +1,6 @@ ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py -; RUN: llc -mattr=+sve -force-streaming-compatible-sve < %s | FileCheck %s -; RUN: llc -mattr=+sme -force-streaming-compatible-sve < %s | FileCheck %s +; RUN: llc -mattr=+sve -force-streaming-compatible < %s | FileCheck %s +; RUN: llc -mattr=+sme -force-streaming-compatible < %s | FileCheck %s target triple = "aarch64-unknown-linux-gnu" diff --git a/llvm/test/CodeGen/AArch64/sve-streaming-mode-fixed-length-fp-convert.ll b/llvm/test/CodeGen/AArch64/sve-streaming-mode-fixed-length-fp-convert.ll index 9bdde14e8d83..57d072a7bcd6 100644 --- a/llvm/test/CodeGen/AArch64/sve-streaming-mode-fixed-length-fp-convert.ll +++ b/llvm/test/CodeGen/AArch64/sve-streaming-mode-fixed-length-fp-convert.ll @@ -1,6 +1,6 @@ ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py -; RUN: llc -mattr=+sve -force-streaming-compatible-sve < %s | FileCheck %s -; RUN: llc -mattr=+sme -force-streaming-compatible-sve < %s | FileCheck %s +; RUN: llc -mattr=+sve -force-streaming-compatible < %s | FileCheck %s +; RUN: llc -mattr=+sme -force-streaming-compatible < %s | FileCheck %s target triple = "aarch64-unknown-linux-gnu" diff --git a/llvm/test/CodeGen/AArch64/sve-streaming-mode-fixed-length-fp-extend-trunc.ll b/llvm/test/CodeGen/AArch64/sve-streaming-mode-fixed-length-fp-extend-trunc.ll index 244a40510173..6a2dc3c71825 100644 --- a/llvm/test/CodeGen/AArch64/sve-streaming-mode-fixed-length-fp-extend-trunc.ll +++ b/llvm/test/CodeGen/AArch64/sve-streaming-mode-fixed-length-fp-extend-trunc.ll @@ -1,6 +1,6 @@ ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py -; RUN: llc -mattr=+sve -force-streaming-compatible-sve < %s | FileCheck %s -; RUN: llc -mattr=+sme -force-streaming-compatible-sve < %s | FileCheck %s +; RUN: llc -mattr=+sve -force-streaming-compatible < %s | FileCheck %s +; RUN: llc -mattr=+sme -force-streaming-compatible < %s | FileCheck %s target triple = "aarch64-unknown-linux-gnu" diff --git a/llvm/test/CodeGen/AArch64/sve-streaming-mode-fixed-length-fp-fma.ll b/llvm/test/CodeGen/AArch64/sve-streaming-mode-fixed-length-fp-fma.ll index cbe71d715a8f..153a04f48657 100644 --- a/llvm/test/CodeGen/AArch64/sve-streaming-mode-fixed-length-fp-fma.ll +++ b/llvm/test/CodeGen/AArch64/sve-streaming-mode-fixed-length-fp-fma.ll @@ -1,5 +1,5 @@ ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py -; RUN: llc -mattr=+sve -force-streaming-compatible-sve < %s | FileCheck %s +; RUN: llc -mattr=+sve -force-streaming-compatible < %s | FileCheck %s target triple = "aarch64-unknown-linux-gnu" diff --git a/llvm/test/CodeGen/AArch64/sve-streaming-mode-fixed-length-fp-minmax.ll b/llvm/test/CodeGen/AArch64/sve-streaming-mode-fixed-length-fp-minmax.ll index 94a74763aa0e..6945a6102c05 100644 --- a/llvm/test/CodeGen/AArch64/sve-streaming-mode-fixed-length-fp-minmax.ll +++ b/llvm/test/CodeGen/AArch64/sve-streaming-mode-fixed-length-fp-minmax.ll @@ -1,6 +1,6 @@ ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py -; RUN: llc -mattr=+sve -force-streaming-compatible-sve < %s | FileCheck %s -; RUN: llc -mattr=+sme -force-streaming-compatible-sve < %s | FileCheck %s +; RUN: llc -mattr=+sve -force-streaming-compatible < %s | FileCheck %s +; RUN: llc -mattr=+sme -force-streaming-compatible < %s | FileCheck %s target triple = "aarch64-unknown-linux-gnu" diff --git a/llvm/test/CodeGen/AArch64/sve-streaming-mode-fixed-length-fp-reduce-fa64.ll b/llvm/test/CodeGen/AArch64/sve-streaming-mode-fixed-length-fp-reduce-fa64.ll index b56e67d95ba0..e239ff5e35fd 100644 --- a/llvm/test/CodeGen/AArch64/sve-streaming-mode-fixed-length-fp-reduce-fa64.ll +++ b/llvm/test/CodeGen/AArch64/sve-streaming-mode-fixed-length-fp-reduce-fa64.ll @@ -1,6 +1,6 @@ ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py -; RUN: llc -mattr=+sme-fa64 -force-streaming-compatible-sve < %s | FileCheck %s -check-prefix=FA64 -; RUN: llc -mattr=+sve -force-streaming-compatible-sve < %s | FileCheck %s -check-prefix=NO-FA64 +; RUN: llc -mattr=+sme-fa64 -force-streaming-compatible < %s | FileCheck %s -check-prefix=FA64 +; RUN: llc -mattr=+sve -force-streaming-compatible < %s | FileCheck %s -check-prefix=NO-FA64 target triple = "aarch64-unknown-linux-gnu" diff --git a/llvm/test/CodeGen/AArch64/sve-streaming-mode-fixed-length-fp-reduce.ll b/llvm/test/CodeGen/AArch64/sve-streaming-mode-fixed-length-fp-reduce.ll index df9613a30e40..78ae7bb6cf30 100644 --- a/llvm/test/CodeGen/AArch64/sve-streaming-mode-fixed-length-fp-reduce.ll +++ b/llvm/test/CodeGen/AArch64/sve-streaming-mode-fixed-length-fp-reduce.ll @@ -1,5 +1,5 @@ ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py -; RUN: llc -mattr=+sve -force-streaming-compatible-sve < %s | FileCheck %s +; RUN: llc -mattr=+sve -force-streaming-compatible < %s | FileCheck %s target triple = "aarch64-unknown-linux-gnu" diff --git a/llvm/test/CodeGen/AArch64/sve-streaming-mode-fixed-length-fp-rounding.ll b/llvm/test/CodeGen/AArch64/sve-streaming-mode-fixed-length-fp-rounding.ll index 7ddc641f366c..412c27cb82f1 100644 --- a/llvm/test/CodeGen/AArch64/sve-streaming-mode-fixed-length-fp-rounding.ll +++ b/llvm/test/CodeGen/AArch64/sve-streaming-mode-fixed-length-fp-rounding.ll @@ -1,6 +1,6 @@ ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py -; RUN: llc -mattr=+sve -force-streaming-compatible-sve < %s | FileCheck %s -; RUN: llc -mattr=+sme -force-streaming-compatible-sve < %s | FileCheck %s +; RUN: llc -mattr=+sve -force-streaming-compatible < %s | FileCheck %s +; RUN: llc -mattr=+sme -force-streaming-compatible < %s | FileCheck %s target triple = "aarch64-unknown-linux-gnu" diff --git a/llvm/test/CodeGen/AArch64/sve-streaming-mode-fixed-length-fp-select.ll b/llvm/test/CodeGen/AArch64/sve-streaming-mode-fixed-length-fp-select.ll index 7d36925fdc57..89697cde848b 100644 --- a/llvm/test/CodeGen/AArch64/sve-streaming-mode-fixed-length-fp-select.ll +++ b/llvm/test/CodeGen/AArch64/sve-streaming-mode-fixed-length-fp-select.ll @@ -1,6 +1,6 @@ ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py -; RUN: llc -mattr=+sve -force-streaming-compatible-sve < %s | FileCheck %s -; RUN: llc -mattr=+sme -force-streaming-compatible-sve < %s | FileCheck %s +; RUN: llc -mattr=+sve -force-streaming-compatible < %s | FileCheck %s +; RUN: llc -mattr=+sme -force-streaming-compatible < %s | FileCheck %s target triple = "aarch64-unknown-linux-gnu" diff --git a/llvm/test/CodeGen/AArch64/sve-streaming-mode-fixed-length-fp-to-int.ll b/llvm/test/CodeGen/AArch64/sve-streaming-mode-fixed-length-fp-to-int.ll index bf8a335a8503..5840ffb20994 100644 --- a/llvm/test/CodeGen/AArch64/sve-streaming-mode-fixed-length-fp-to-int.ll +++ b/llvm/test/CodeGen/AArch64/sve-streaming-mode-fixed-length-fp-to-int.ll @@ -1,5 +1,5 @@ ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py -; RUN: llc -mattr=+sve -force-streaming-compatible-sve < %s | FileCheck %s +; RUN: llc -mattr=+sve -force-streaming-compatible < %s | FileCheck %s target triple = "aarch64-unknown-linux-gnu" diff --git a/llvm/test/CodeGen/AArch64/sve-streaming-mode-fixed-length-fp-vselect.ll b/llvm/test/CodeGen/AArch64/sve-streaming-mode-fixed-length-fp-vselect.ll index 30a4f04a3d2b..c1c7b5c05f5d 100644 --- a/llvm/test/CodeGen/AArch64/sve-streaming-mode-fixed-length-fp-vselect.ll +++ b/llvm/test/CodeGen/AArch64/sve-streaming-mode-fixed-length-fp-vselect.ll @@ -1,6 +1,6 @@ ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py -; RUN: llc -mattr=+sve -force-streaming-compatible-sve < %s | FileCheck %s -; RUN: llc -mattr=+sme -force-streaming-compatible-sve < %s | FileCheck %s +; RUN: llc -mattr=+sve -force-streaming-compatible < %s | FileCheck %s +; RUN: llc -mattr=+sme -force-streaming-compatible < %s | FileCheck %s target triple = "aarch64-unknown-linux-gnu" diff --git a/llvm/test/CodeGen/AArch64/sve-streaming-mode-fixed-length-insert-vector-elt.ll b/llvm/test/CodeGen/AArch64/sve-streaming-mode-fixed-length-insert-vector-elt.ll index 4aa965777c74..ff38db8c10c0 100644 --- a/llvm/test/CodeGen/AArch64/sve-streaming-mode-fixed-length-insert-vector-elt.ll +++ b/llvm/test/CodeGen/AArch64/sve-streaming-mode-fixed-length-insert-vector-elt.ll @@ -1,5 +1,5 @@ ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py -; RUN: llc -mattr=+sve -force-streaming-compatible-sve < %s | FileCheck %s +; RUN: llc -mattr=+sve -force-streaming-compatible < %s | FileCheck %s target triple = "aarch64-unknown-linux-gnu" diff --git a/llvm/test/CodeGen/AArch64/sve-streaming-mode-fixed-length-int-arith.ll b/llvm/test/CodeGen/AArch64/sve-streaming-mode-fixed-length-int-arith.ll index 8baa87c6d686..ee1706bc7c35 100644 --- a/llvm/test/CodeGen/AArch64/sve-streaming-mode-fixed-length-int-arith.ll +++ b/llvm/test/CodeGen/AArch64/sve-streaming-mode-fixed-length-int-arith.ll @@ -1,7 +1,7 @@ ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py -; RUN: llc -mattr=+sve -force-streaming-compatible-sve < %s | FileCheck %s --check-prefixes=CHECK,SVE -; RUN: llc -mattr=+sve2 -force-streaming-compatible-sve < %s | FileCheck %s --check-prefixes=CHECK,SVE2 -; RUN: llc -mattr=+sme -force-streaming-compatible-sve < %s | FileCheck %s --check-prefixes=CHECK,SVE2 +; RUN: llc -mattr=+sve -force-streaming-compatible < %s | FileCheck %s --check-prefixes=CHECK,SVE +; RUN: llc -mattr=+sve2 -force-streaming-compatible < %s | FileCheck %s --check-prefixes=CHECK,SVE2 +; RUN: llc -mattr=+sme -force-streaming-compatible < %s | FileCheck %s --check-prefixes=CHECK,SVE2 target triple = "aarch64-unknown-linux-gnu" diff --git a/llvm/test/CodeGen/AArch64/sve-streaming-mode-fixed-length-int-compares.ll b/llvm/test/CodeGen/AArch64/sve-streaming-mode-fixed-length-int-compares.ll index 73c1eac99dd3..c2f3bbfb51dd 100644 --- a/llvm/test/CodeGen/AArch64/sve-streaming-mode-fixed-length-int-compares.ll +++ b/llvm/test/CodeGen/AArch64/sve-streaming-mode-fixed-length-int-compares.ll @@ -1,6 +1,6 @@ ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py -; RUN: llc -mattr=+sve -force-streaming-compatible-sve < %s | FileCheck %s -; RUN: llc -mattr=+sme -force-streaming-compatible-sve < %s | FileCheck %s +; RUN: llc -mattr=+sve -force-streaming-compatible < %s | FileCheck %s +; RUN: llc -mattr=+sme -force-streaming-compatible < %s | FileCheck %s target triple = "aarch64-unknown-linux-gnu" diff --git a/llvm/test/CodeGen/AArch64/sve-streaming-mode-fixed-length-int-div.ll b/llvm/test/CodeGen/AArch64/sve-streaming-mode-fixed-length-int-div.ll index 5158dda37a8b..e6fd775b4cfb 100644 --- a/llvm/test/CodeGen/AArch64/sve-streaming-mode-fixed-length-int-div.ll +++ b/llvm/test/CodeGen/AArch64/sve-streaming-mode-fixed-length-int-div.ll @@ -1,7 +1,7 @@ ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py -; RUN: llc -mattr=+sve -force-streaming-compatible-sve < %s | FileCheck %s --check-prefixes=CHECK,SVE -; RUN: llc -mattr=+sve2 -force-streaming-compatible-sve < %s | FileCheck %s --check-prefixes=CHECK,SVE2 -; RUN: llc -mattr=+sme -force-streaming-compatible-sve < %s | FileCheck %s --check-prefixes=CHECK,SVE2 +; RUN: llc -mattr=+sve -force-streaming-compatible < %s | FileCheck %s --check-prefixes=CHECK,SVE +; RUN: llc -mattr=+sve2 -force-streaming-compatible < %s | FileCheck %s --check-prefixes=CHECK,SVE2 +; RUN: llc -mattr=+sme -force-streaming-compatible < %s | FileCheck %s --check-prefixes=CHECK,SVE2 target triple = "aarch64-unknown-linux-gnu" diff --git a/llvm/test/CodeGen/AArch64/sve-streaming-mode-fixed-length-int-extends.ll b/llvm/test/CodeGen/AArch64/sve-streaming-mode-fixed-length-int-extends.ll index c7a89612d278..e40668a8696e 100644 --- a/llvm/test/CodeGen/AArch64/sve-streaming-mode-fixed-length-int-extends.ll +++ b/llvm/test/CodeGen/AArch64/sve-streaming-mode-fixed-length-int-extends.ll @@ -1,7 +1,7 @@ ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py -; RUN: llc -mattr=+sve -force-streaming-compatible-sve < %s | FileCheck %s --check-prefixes=CHECK,SVE -; RUN: llc -mattr=+sve2 -force-streaming-compatible-sve < %s | FileCheck %s --check-prefixes=CHECK,SVE2 -; RUN: llc -mattr=+sme -force-streaming-compatible-sve < %s | FileCheck %s --check-prefixes=CHECK,SVE2 +; RUN: llc -mattr=+sve -force-streaming-compatible < %s | FileCheck %s --check-prefixes=CHECK,SVE +; RUN: llc -mattr=+sve2 -force-streaming-compatible < %s | FileCheck %s --check-prefixes=CHECK,SVE2 +; RUN: llc -mattr=+sme -force-streaming-compatible < %s | FileCheck %s --check-prefixes=CHECK,SVE2 target triple = "aarch64-unknown-linux-gnu" diff --git a/llvm/test/CodeGen/AArch64/sve-streaming-mode-fixed-length-int-immediates.ll b/llvm/test/CodeGen/AArch64/sve-streaming-mode-fixed-length-int-immediates.ll index f028b3eeca25..54276bb4ba01 100644 --- a/llvm/test/CodeGen/AArch64/sve-streaming-mode-fixed-length-int-immediates.ll +++ b/llvm/test/CodeGen/AArch64/sve-streaming-mode-fixed-length-int-immediates.ll @@ -1,6 +1,6 @@ ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py -; RUN: llc -mattr=+sve -force-streaming-compatible-sve < %s | FileCheck %s -; RUN: llc -mattr=+sme -force-streaming-compatible-sve < %s | FileCheck %s +; RUN: llc -mattr=+sve -force-streaming-compatible < %s | FileCheck %s +; RUN: llc -mattr=+sme -force-streaming-compatible < %s | FileCheck %s target triple = "aarch64-unknown-linux-gnu" diff --git a/llvm/test/CodeGen/AArch64/sve-streaming-mode-fixed-length-int-log.ll b/llvm/test/CodeGen/AArch64/sve-streaming-mode-fixed-length-int-log.ll index 4d70c1dd1c91..40824ba9ae9c 100644 --- a/llvm/test/CodeGen/AArch64/sve-streaming-mode-fixed-length-int-log.ll +++ b/llvm/test/CodeGen/AArch64/sve-streaming-mode-fixed-length-int-log.ll @@ -1,6 +1,6 @@ ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py -; RUN: llc -mattr=+sve -force-streaming-compatible-sve < %s | FileCheck %s -; RUN: llc -mattr=+sme -force-streaming-compatible-sve < %s | FileCheck %s +; RUN: llc -mattr=+sve -force-streaming-compatible < %s | FileCheck %s +; RUN: llc -mattr=+sme -force-streaming-compatible < %s | FileCheck %s target triple = "aarch64-unknown-linux-gnu" diff --git a/llvm/test/CodeGen/AArch64/sve-streaming-mode-fixed-length-int-minmax.ll b/llvm/test/CodeGen/AArch64/sve-streaming-mode-fixed-length-int-minmax.ll index 50cf9b73d9a7..74ee5482a60c 100644 --- a/llvm/test/CodeGen/AArch64/sve-streaming-mode-fixed-length-int-minmax.ll +++ b/llvm/test/CodeGen/AArch64/sve-streaming-mode-fixed-length-int-minmax.ll @@ -1,6 +1,6 @@ ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py -; RUN: llc -mattr=+sve -force-streaming-compatible-sve < %s | FileCheck %s -; RUN: llc -mattr=+sme -force-streaming-compatible-sve < %s | FileCheck %s +; RUN: llc -mattr=+sve -force-streaming-compatible < %s | FileCheck %s +; RUN: llc -mattr=+sme -force-streaming-compatible < %s | FileCheck %s target triple = "aarch64-unknown-linux-gnu" diff --git a/llvm/test/CodeGen/AArch64/sve-streaming-mode-fixed-length-int-mla-neon-fa64.ll b/llvm/test/CodeGen/AArch64/sve-streaming-mode-fixed-length-int-mla-neon-fa64.ll index 149ad6d1e267..3ff6983210a0 100644 --- a/llvm/test/CodeGen/AArch64/sve-streaming-mode-fixed-length-int-mla-neon-fa64.ll +++ b/llvm/test/CodeGen/AArch64/sve-streaming-mode-fixed-length-int-mla-neon-fa64.ll @@ -1,6 +1,6 @@ ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py -; RUN: llc -mattr=+sme-fa64 -force-streaming-compatible-sve < %s | FileCheck %s -check-prefix=FA64 -; RUN: llc -mattr=+sve -force-streaming-compatible-sve < %s | FileCheck %s -check-prefix=NO-FA64 +; RUN: llc -mattr=+sme-fa64 -force-streaming-compatible < %s | FileCheck %s -check-prefix=FA64 +; RUN: llc -mattr=+sve -force-streaming-compatible < %s | FileCheck %s -check-prefix=NO-FA64 target triple = "aarch64-unknown-linux-gnu" diff --git a/llvm/test/CodeGen/AArch64/sve-streaming-mode-fixed-length-int-mulh.ll b/llvm/test/CodeGen/AArch64/sve-streaming-mode-fixed-length-int-mulh.ll index cb7fa53eac51..8917f43002da 100644 --- a/llvm/test/CodeGen/AArch64/sve-streaming-mode-fixed-length-int-mulh.ll +++ b/llvm/test/CodeGen/AArch64/sve-streaming-mode-fixed-length-int-mulh.ll @@ -1,7 +1,7 @@ ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py -; RUN: llc -mattr=+sve -force-streaming-compatible-sve < %s | FileCheck %s --check-prefixes=CHECK,SVE -; RUN: llc -mattr=+sve2 -force-streaming-compatible-sve < %s | FileCheck %s --check-prefixes=CHECK,SVE2 -; RUN: llc -mattr=+sme -force-streaming-compatible-sve < %s | FileCheck %s --check-prefixes=CHECK,SVE2 +; RUN: llc -mattr=+sve -force-streaming-compatible < %s | FileCheck %s --check-prefixes=CHECK,SVE +; RUN: llc -mattr=+sve2 -force-streaming-compatible < %s | FileCheck %s --check-prefixes=CHECK,SVE2 +; RUN: llc -mattr=+sme -force-streaming-compatible < %s | FileCheck %s --check-prefixes=CHECK,SVE2 ; This test only tests the legal types for a given vector width, as mulh nodes ; do not get generated for non-legal types. diff --git a/llvm/test/CodeGen/AArch64/sve-streaming-mode-fixed-length-int-reduce.ll b/llvm/test/CodeGen/AArch64/sve-streaming-mode-fixed-length-int-reduce.ll index 751f43768a51..1123907f3389 100644 --- a/llvm/test/CodeGen/AArch64/sve-streaming-mode-fixed-length-int-reduce.ll +++ b/llvm/test/CodeGen/AArch64/sve-streaming-mode-fixed-length-int-reduce.ll @@ -1,6 +1,6 @@ ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py -; RUN: llc -mattr=+sve -force-streaming-compatible-sve < %s | FileCheck %s -; RUN: llc -mattr=+sme -force-streaming-compatible-sve < %s | FileCheck %s +; RUN: llc -mattr=+sve -force-streaming-compatible < %s | FileCheck %s +; RUN: llc -mattr=+sme -force-streaming-compatible < %s | FileCheck %s target triple = "aarch64-unknown-linux-gnu" diff --git a/llvm/test/CodeGen/AArch64/sve-streaming-mode-fixed-length-int-rem.ll b/llvm/test/CodeGen/AArch64/sve-streaming-mode-fixed-length-int-rem.ll index d373a9063f85..4ae7586fca16 100644 --- a/llvm/test/CodeGen/AArch64/sve-streaming-mode-fixed-length-int-rem.ll +++ b/llvm/test/CodeGen/AArch64/sve-streaming-mode-fixed-length-int-rem.ll @@ -1,6 +1,6 @@ ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py -; RUN: llc -mattr=+sve -force-streaming-compatible-sve < %s | FileCheck %s -; RUN: llc -mattr=+sme -force-streaming-compatible-sve < %s | FileCheck %s +; RUN: llc -mattr=+sve -force-streaming-compatible < %s | FileCheck %s +; RUN: llc -mattr=+sme -force-streaming-compatible < %s | FileCheck %s target triple = "aarch64-unknown-linux-gnu" diff --git a/llvm/test/CodeGen/AArch64/sve-streaming-mode-fixed-length-int-select.ll b/llvm/test/CodeGen/AArch64/sve-streaming-mode-fixed-length-int-select.ll index 906112f7ac39..bfffe4b6315d 100644 --- a/llvm/test/CodeGen/AArch64/sve-streaming-mode-fixed-length-int-select.ll +++ b/llvm/test/CodeGen/AArch64/sve-streaming-mode-fixed-length-int-select.ll @@ -1,6 +1,6 @@ ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py -; RUN: llc -mattr=+sve -force-streaming-compatible-sve < %s | FileCheck %s -; RUN: llc -mattr=+sme -force-streaming-compatible-sve < %s | FileCheck %s +; RUN: llc -mattr=+sve -force-streaming-compatible < %s | FileCheck %s +; RUN: llc -mattr=+sme -force-streaming-compatible < %s | FileCheck %s target triple = "aarch64-unknown-linux-gnu" diff --git a/llvm/test/CodeGen/AArch64/sve-streaming-mode-fixed-length-int-shifts.ll b/llvm/test/CodeGen/AArch64/sve-streaming-mode-fixed-length-int-shifts.ll index 9ed52e321d9a..9319bd69c25f 100644 --- a/llvm/test/CodeGen/AArch64/sve-streaming-mode-fixed-length-int-shifts.ll +++ b/llvm/test/CodeGen/AArch64/sve-streaming-mode-fixed-length-int-shifts.ll @@ -1,6 +1,6 @@ ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py -; RUN: llc -mattr=+sve -force-streaming-compatible-sve < %s | FileCheck %s -; RUN: llc -mattr=+sme -force-streaming-compatible-sve < %s | FileCheck %s +; RUN: llc -mattr=+sve -force-streaming-compatible < %s | FileCheck %s +; RUN: llc -mattr=+sme -force-streaming-compatible < %s | FileCheck %s target triple = "aarch64-unknown-linux-gnu" diff --git a/llvm/test/CodeGen/AArch64/sve-streaming-mode-fixed-length-int-to-fp.ll b/llvm/test/CodeGen/AArch64/sve-streaming-mode-fixed-length-int-to-fp.ll index a9b52c93006d..27dbfc9a23a8 100644 --- a/llvm/test/CodeGen/AArch64/sve-streaming-mode-fixed-length-int-to-fp.ll +++ b/llvm/test/CodeGen/AArch64/sve-streaming-mode-fixed-length-int-to-fp.ll @@ -1,5 +1,5 @@ ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py -; RUN: llc -mattr=+sve -force-streaming-compatible-sve < %s | FileCheck %s +; RUN: llc -mattr=+sve -force-streaming-compatible < %s | FileCheck %s target triple = "aarch64-unknown-linux-gnu" diff --git a/llvm/test/CodeGen/AArch64/sve-streaming-mode-fixed-length-int-vselect.ll b/llvm/test/CodeGen/AArch64/sve-streaming-mode-fixed-length-int-vselect.ll index 81bbaa92d4b4..3775a64a89a0 100644 --- a/llvm/test/CodeGen/AArch64/sve-streaming-mode-fixed-length-int-vselect.ll +++ b/llvm/test/CodeGen/AArch64/sve-streaming-mode-fixed-length-int-vselect.ll @@ -1,6 +1,6 @@ ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py -; RUN: llc -mattr=+sve -force-streaming-compatible-sve < %s | FileCheck %s -; RUN: llc -mattr=+sme -force-streaming-compatible-sve < %s | FileCheck %s +; RUN: llc -mattr=+sve -force-streaming-compatible < %s | FileCheck %s +; RUN: llc -mattr=+sme -force-streaming-compatible < %s | FileCheck %s target triple = "aarch64-unknown-linux-gnu" diff --git a/llvm/test/CodeGen/AArch64/sve-streaming-mode-fixed-length-ld2-alloca.ll b/llvm/test/CodeGen/AArch64/sve-streaming-mode-fixed-length-ld2-alloca.ll index 318285ded5a8..0b6152340f65 100644 --- a/llvm/test/CodeGen/AArch64/sve-streaming-mode-fixed-length-ld2-alloca.ll +++ b/llvm/test/CodeGen/AArch64/sve-streaming-mode-fixed-length-ld2-alloca.ll @@ -1,7 +1,7 @@ ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py -; RUN: llc -mattr=+sve -force-streaming-compatible-sve < %s | FileCheck %s -; RUN: llc -mattr=+sme -force-streaming-compatible-sve < %s | FileCheck %s -; RUN: llc -force-streaming-compatible-sve < %s | FileCheck %s --check-prefix=NONEON-NOSVE +; RUN: llc -mattr=+sve -force-streaming-compatible < %s | FileCheck %s +; RUN: llc -mattr=+sme -force-streaming-compatible < %s | FileCheck %s +; RUN: llc -force-streaming-compatible < %s | FileCheck %s --check-prefix=NONEON-NOSVE target triple = "aarch64-unknown-linux-gnu" diff --git a/llvm/test/CodeGen/AArch64/sve-streaming-mode-fixed-length-limit-duplane.ll b/llvm/test/CodeGen/AArch64/sve-streaming-mode-fixed-length-limit-duplane.ll index 885030861469..918f0ccc0cf6 100644 --- a/llvm/test/CodeGen/AArch64/sve-streaming-mode-fixed-length-limit-duplane.ll +++ b/llvm/test/CodeGen/AArch64/sve-streaming-mode-fixed-length-limit-duplane.ll @@ -1,6 +1,6 @@ ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py -; RUN: llc -mattr=+sve -force-streaming-compatible-sve < %s | FileCheck %s -; RUN: llc -mattr=+sme -force-streaming-compatible-sve < %s | FileCheck %s +; RUN: llc -mattr=+sve -force-streaming-compatible < %s | FileCheck %s +; RUN: llc -mattr=+sme -force-streaming-compatible < %s | FileCheck %s target triple = "aarch64-unknown-linux-gnu" diff --git a/llvm/test/CodeGen/AArch64/sve-streaming-mode-fixed-length-loads.ll b/llvm/test/CodeGen/AArch64/sve-streaming-mode-fixed-length-loads.ll index 8ca8e6980913..8c69d5b0bb37 100644 --- a/llvm/test/CodeGen/AArch64/sve-streaming-mode-fixed-length-loads.ll +++ b/llvm/test/CodeGen/AArch64/sve-streaming-mode-fixed-length-loads.ll @@ -1,6 +1,6 @@ ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py -; RUN: llc -mattr=+sve -force-streaming-compatible-sve < %s | FileCheck %s -; RUN: llc -mattr=+sme -force-streaming-compatible-sve < %s | FileCheck %s +; RUN: llc -mattr=+sve -force-streaming-compatible < %s | FileCheck %s +; RUN: llc -mattr=+sme -force-streaming-compatible < %s | FileCheck %s target triple = "aarch64-unknown-linux-gnu" diff --git a/llvm/test/CodeGen/AArch64/sve-streaming-mode-fixed-length-log-reduce.ll b/llvm/test/CodeGen/AArch64/sve-streaming-mode-fixed-length-log-reduce.ll index c4aeb4465c53..ef52eadc5d3b 100644 --- a/llvm/test/CodeGen/AArch64/sve-streaming-mode-fixed-length-log-reduce.ll +++ b/llvm/test/CodeGen/AArch64/sve-streaming-mode-fixed-length-log-reduce.ll @@ -1,6 +1,6 @@ ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py -; RUN: llc -mattr=+sve -force-streaming-compatible-sve < %s | FileCheck %s -; RUN: llc -mattr=+sme -force-streaming-compatible-sve < %s | FileCheck %s +; RUN: llc -mattr=+sve -force-streaming-compatible < %s | FileCheck %s +; RUN: llc -mattr=+sme -force-streaming-compatible < %s | FileCheck %s target triple = "aarch64-unknown-linux-gnu" diff --git a/llvm/test/CodeGen/AArch64/sve-streaming-mode-fixed-length-masked-load.ll b/llvm/test/CodeGen/AArch64/sve-streaming-mode-fixed-length-masked-load.ll index ca58099244cf..4f8f8c2e4b24 100644 --- a/llvm/test/CodeGen/AArch64/sve-streaming-mode-fixed-length-masked-load.ll +++ b/llvm/test/CodeGen/AArch64/sve-streaming-mode-fixed-length-masked-load.ll @@ -1,5 +1,5 @@ ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py -; RUN: llc -mattr=+sve -force-streaming-compatible-sve < %s | FileCheck %s +; RUN: llc -mattr=+sve -force-streaming-compatible < %s | FileCheck %s target triple = "aarch64-unknown-linux-gnu" diff --git a/llvm/test/CodeGen/AArch64/sve-streaming-mode-fixed-length-masked-store.ll b/llvm/test/CodeGen/AArch64/sve-streaming-mode-fixed-length-masked-store.ll index f2b3f9b12ea7..bd6b96889b4c 100644 --- a/llvm/test/CodeGen/AArch64/sve-streaming-mode-fixed-length-masked-store.ll +++ b/llvm/test/CodeGen/AArch64/sve-streaming-mode-fixed-length-masked-store.ll @@ -1,5 +1,5 @@ ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py -; RUN: llc -mattr=+sve -force-streaming-compatible-sve < %s | FileCheck %s +; RUN: llc -mattr=+sve -force-streaming-compatible < %s | FileCheck %s target triple = "aarch64-unknown-linux-gnu" diff --git a/llvm/test/CodeGen/AArch64/sve-streaming-mode-fixed-length-optimize-ptrue.ll b/llvm/test/CodeGen/AArch64/sve-streaming-mode-fixed-length-optimize-ptrue.ll index b5adea594242..aef446a90df6 100644 --- a/llvm/test/CodeGen/AArch64/sve-streaming-mode-fixed-length-optimize-ptrue.ll +++ b/llvm/test/CodeGen/AArch64/sve-streaming-mode-fixed-length-optimize-ptrue.ll @@ -1,6 +1,6 @@ ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py -; RUN: llc -mattr=+sve -force-streaming-compatible-sve < %s | FileCheck %s -; RUN: llc -mattr=+sme -force-streaming-compatible-sve < %s | FileCheck %s +; RUN: llc -mattr=+sve -force-streaming-compatible < %s | FileCheck %s +; RUN: llc -mattr=+sme -force-streaming-compatible < %s | FileCheck %s target triple = "aarch64-unknown-linux-gnu" diff --git a/llvm/test/CodeGen/AArch64/sve-streaming-mode-fixed-length-permute-rev.ll b/llvm/test/CodeGen/AArch64/sve-streaming-mode-fixed-length-permute-rev.ll index 00413302798c..6d91253caae5 100644 --- a/llvm/test/CodeGen/AArch64/sve-streaming-mode-fixed-length-permute-rev.ll +++ b/llvm/test/CodeGen/AArch64/sve-streaming-mode-fixed-length-permute-rev.ll @@ -1,6 +1,6 @@ ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py -; RUN: llc -mattr=+sve -force-streaming-compatible-sve < %s | FileCheck %s -; RUN: llc -mattr=+sme -force-streaming-compatible-sve < %s | FileCheck %s +; RUN: llc -mattr=+sve -force-streaming-compatible < %s | FileCheck %s +; RUN: llc -mattr=+sme -force-streaming-compatible < %s | FileCheck %s target triple = "aarch64-unknown-linux-gnu" diff --git a/llvm/test/CodeGen/AArch64/sve-streaming-mode-fixed-length-permute-zip-uzp-trn.ll b/llvm/test/CodeGen/AArch64/sve-streaming-mode-fixed-length-permute-zip-uzp-trn.ll index cb73030306b0..8808ad9a23d7 100644 --- a/llvm/test/CodeGen/AArch64/sve-streaming-mode-fixed-length-permute-zip-uzp-trn.ll +++ b/llvm/test/CodeGen/AArch64/sve-streaming-mode-fixed-length-permute-zip-uzp-trn.ll @@ -1,6 +1,6 @@ ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py -; RUN: llc -mattr=+sve -force-streaming-compatible-sve < %s | FileCheck %s -; RUN: llc -mattr=+sme -force-streaming-compatible-sve < %s | FileCheck %s +; RUN: llc -mattr=+sve -force-streaming-compatible < %s | FileCheck %s +; RUN: llc -mattr=+sme -force-streaming-compatible < %s | FileCheck %s target triple = "aarch64-unknown-linux-gnu" diff --git a/llvm/test/CodeGen/AArch64/sve-streaming-mode-fixed-length-ptest.ll b/llvm/test/CodeGen/AArch64/sve-streaming-mode-fixed-length-ptest.ll index ab7c42b3e9e3..8039bd096bcb 100644 --- a/llvm/test/CodeGen/AArch64/sve-streaming-mode-fixed-length-ptest.ll +++ b/llvm/test/CodeGen/AArch64/sve-streaming-mode-fixed-length-ptest.ll @@ -1,6 +1,6 @@ ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py -; RUN: llc -mattr=+sve -force-streaming-compatible-sve < %s | FileCheck %s -; RUN: llc -mattr=+sme -force-streaming-compatible-sve < %s | FileCheck %s +; RUN: llc -mattr=+sve -force-streaming-compatible < %s | FileCheck %s +; RUN: llc -mattr=+sme -force-streaming-compatible < %s | FileCheck %s target triple = "aarch64-unknown-linux-gnu" diff --git a/llvm/test/CodeGen/AArch64/sve-streaming-mode-fixed-length-reshuffle.ll b/llvm/test/CodeGen/AArch64/sve-streaming-mode-fixed-length-reshuffle.ll index 362612518787..9741147b332e 100644 --- a/llvm/test/CodeGen/AArch64/sve-streaming-mode-fixed-length-reshuffle.ll +++ b/llvm/test/CodeGen/AArch64/sve-streaming-mode-fixed-length-reshuffle.ll @@ -1,6 +1,6 @@ ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py -; RUN: llc -mattr=+sve -force-streaming-compatible-sve < %s | FileCheck %s -; RUN: llc -mattr=+sme -force-streaming-compatible-sve < %s | FileCheck %s +; RUN: llc -mattr=+sve -force-streaming-compatible < %s | FileCheck %s +; RUN: llc -mattr=+sme -force-streaming-compatible < %s | FileCheck %s target triple = "aarch64-unknown-linux-gnu" diff --git a/llvm/test/CodeGen/AArch64/sve-streaming-mode-fixed-length-rev.ll b/llvm/test/CodeGen/AArch64/sve-streaming-mode-fixed-length-rev.ll index bfa931044bc5..726fd28c90ae 100644 --- a/llvm/test/CodeGen/AArch64/sve-streaming-mode-fixed-length-rev.ll +++ b/llvm/test/CodeGen/AArch64/sve-streaming-mode-fixed-length-rev.ll @@ -1,6 +1,6 @@ ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py -; RUN: llc -mattr=+sve -force-streaming-compatible-sve < %s | FileCheck %s -; RUN: llc -mattr=+sme -force-streaming-compatible-sve < %s | FileCheck %s +; RUN: llc -mattr=+sve -force-streaming-compatible < %s | FileCheck %s +; RUN: llc -mattr=+sme -force-streaming-compatible < %s | FileCheck %s target triple = "aarch64-unknown-linux-gnu" diff --git a/llvm/test/CodeGen/AArch64/sve-streaming-mode-fixed-length-sdiv-pow2.ll b/llvm/test/CodeGen/AArch64/sve-streaming-mode-fixed-length-sdiv-pow2.ll index 9dd42e7831e0..c022bf85e67e 100644 --- a/llvm/test/CodeGen/AArch64/sve-streaming-mode-fixed-length-sdiv-pow2.ll +++ b/llvm/test/CodeGen/AArch64/sve-streaming-mode-fixed-length-sdiv-pow2.ll @@ -1,6 +1,6 @@ ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py -; RUN: llc -mattr=+sve -force-streaming-compatible-sve < %s | FileCheck %s -; RUN: llc -mattr=+sme -force-streaming-compatible-sve < %s | FileCheck %s +; RUN: llc -mattr=+sve -force-streaming-compatible < %s | FileCheck %s +; RUN: llc -mattr=+sme -force-streaming-compatible < %s | FileCheck %s target triple = "aarch64-unknown-linux-gnu" diff --git a/llvm/test/CodeGen/AArch64/sve-streaming-mode-fixed-length-shuffle.ll b/llvm/test/CodeGen/AArch64/sve-streaming-mode-fixed-length-shuffle.ll index 6f82c97f3b87..38aaf860b729 100644 --- a/llvm/test/CodeGen/AArch64/sve-streaming-mode-fixed-length-shuffle.ll +++ b/llvm/test/CodeGen/AArch64/sve-streaming-mode-fixed-length-shuffle.ll @@ -1,7 +1,7 @@ ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py -; RUN: llc -mattr=+sve -force-streaming-compatible-sve < %s | FileCheck %s -; RUN: llc -mattr=+sme -force-streaming-compatible-sve < %s | FileCheck %s -; RUN: llc -force-streaming-compatible-sve < %s | FileCheck %s --check-prefix=NONEON-NOSVE +; RUN: llc -mattr=+sve -force-streaming-compatible < %s | FileCheck %s +; RUN: llc -mattr=+sme -force-streaming-compatible < %s | FileCheck %s +; RUN: llc -force-streaming-compatible < %s | FileCheck %s --check-prefix=NONEON-NOSVE target triple = "aarch64-unknown-linux-gnu" diff --git a/llvm/test/CodeGen/AArch64/sve-streaming-mode-fixed-length-splat-vector.ll b/llvm/test/CodeGen/AArch64/sve-streaming-mode-fixed-length-splat-vector.ll index 323d5278592f..649b13fa8a1e 100644 --- a/llvm/test/CodeGen/AArch64/sve-streaming-mode-fixed-length-splat-vector.ll +++ b/llvm/test/CodeGen/AArch64/sve-streaming-mode-fixed-length-splat-vector.ll @@ -1,5 +1,5 @@ ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py -; RUN: llc -mattr=+sve -force-streaming-compatible-sve < %s | FileCheck %s +; RUN: llc -mattr=+sve -force-streaming-compatible < %s | FileCheck %s diff --git a/llvm/test/CodeGen/AArch64/sve-streaming-mode-fixed-length-stores.ll b/llvm/test/CodeGen/AArch64/sve-streaming-mode-fixed-length-stores.ll index 06709ca3685c..c7435bdbec94 100644 --- a/llvm/test/CodeGen/AArch64/sve-streaming-mode-fixed-length-stores.ll +++ b/llvm/test/CodeGen/AArch64/sve-streaming-mode-fixed-length-stores.ll @@ -1,6 +1,6 @@ ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py -; RUN: llc -mattr=+sve -force-streaming-compatible-sve < %s | FileCheck %s -; RUN: llc -mattr=+sme -force-streaming-compatible-sve < %s | FileCheck %s +; RUN: llc -mattr=+sve -force-streaming-compatible < %s | FileCheck %s +; RUN: llc -mattr=+sme -force-streaming-compatible < %s | FileCheck %s target triple = "aarch64-unknown-linux-gnu" diff --git a/llvm/test/CodeGen/AArch64/sve-streaming-mode-fixed-length-subvector.ll b/llvm/test/CodeGen/AArch64/sve-streaming-mode-fixed-length-subvector.ll index 838db0ce8185..9e04fc236836 100644 --- a/llvm/test/CodeGen/AArch64/sve-streaming-mode-fixed-length-subvector.ll +++ b/llvm/test/CodeGen/AArch64/sve-streaming-mode-fixed-length-subvector.ll @@ -1,6 +1,6 @@ ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py -; RUN: llc -mattr=+sve -force-streaming-compatible-sve < %s | FileCheck %s -; RUN: llc -mattr=+sme -force-streaming-compatible-sve < %s | FileCheck %s +; RUN: llc -mattr=+sve -force-streaming-compatible < %s | FileCheck %s +; RUN: llc -mattr=+sme -force-streaming-compatible < %s | FileCheck %s ; Test we can code generater patterns of the form: diff --git a/llvm/test/CodeGen/AArch64/sve-streaming-mode-fixed-length-trunc-stores.ll b/llvm/test/CodeGen/AArch64/sve-streaming-mode-fixed-length-trunc-stores.ll index 7e3a175c40d2..b34fe438a063 100644 --- a/llvm/test/CodeGen/AArch64/sve-streaming-mode-fixed-length-trunc-stores.ll +++ b/llvm/test/CodeGen/AArch64/sve-streaming-mode-fixed-length-trunc-stores.ll @@ -1,6 +1,6 @@ ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py -; RUN: llc -mattr=+sve -force-streaming-compatible-sve < %s | FileCheck %s -; RUN: llc -mattr=+sme -force-streaming-compatible-sve < %s | FileCheck %s +; RUN: llc -mattr=+sve -force-streaming-compatible < %s | FileCheck %s +; RUN: llc -mattr=+sme -force-streaming-compatible < %s | FileCheck %s target triple = "aarch64-unknown-linux-gnu" diff --git a/llvm/test/CodeGen/AArch64/sve-streaming-mode-fixed-length-trunc.ll b/llvm/test/CodeGen/AArch64/sve-streaming-mode-fixed-length-trunc.ll index 70219dd30f76..9e56462df388 100644 --- a/llvm/test/CodeGen/AArch64/sve-streaming-mode-fixed-length-trunc.ll +++ b/llvm/test/CodeGen/AArch64/sve-streaming-mode-fixed-length-trunc.ll @@ -1,6 +1,6 @@ ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py -; RUN: llc -mattr=+sve -force-streaming-compatible-sve < %s | FileCheck %s -; RUN: llc -mattr=+sme -force-streaming-compatible-sve < %s | FileCheck %s +; RUN: llc -mattr=+sve -force-streaming-compatible < %s | FileCheck %s +; RUN: llc -mattr=+sme -force-streaming-compatible < %s | FileCheck %s target triple = "aarch64-unknown-linux-gnu" diff --git a/llvm/test/CodeGen/AArch64/sve-streaming-mode-fixed-length-vector-shuffle.ll b/llvm/test/CodeGen/AArch64/sve-streaming-mode-fixed-length-vector-shuffle.ll index 175731480407..304823c9e641 100644 --- a/llvm/test/CodeGen/AArch64/sve-streaming-mode-fixed-length-vector-shuffle.ll +++ b/llvm/test/CodeGen/AArch64/sve-streaming-mode-fixed-length-vector-shuffle.ll @@ -1,6 +1,6 @@ ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py -; RUN: llc -mattr=+sve -force-streaming-compatible-sve < %s | FileCheck %s -; RUN: llc -mattr=+sme -force-streaming-compatible-sve < %s | FileCheck %s +; RUN: llc -mattr=+sve -force-streaming-compatible < %s | FileCheck %s +; RUN: llc -mattr=+sme -force-streaming-compatible < %s | FileCheck %s target triple = "aarch64-unknown-linux-gnu" diff --git a/llvm/test/CodeGen/AArch64/sve-streaming-mode-test-register-mov.ll b/llvm/test/CodeGen/AArch64/sve-streaming-mode-test-register-mov.ll index 337a2134de5b..6c9c05560566 100644 --- a/llvm/test/CodeGen/AArch64/sve-streaming-mode-test-register-mov.ll +++ b/llvm/test/CodeGen/AArch64/sve-streaming-mode-test-register-mov.ll @@ -1,6 +1,6 @@ ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py -; RUN: llc -mattr=+sve -force-streaming-compatible-sve < %s | FileCheck %s -; RUN: llc -mattr=+sme -force-streaming-compatible-sve < %s | FileCheck %s +; RUN: llc -mattr=+sve -force-streaming-compatible < %s | FileCheck %s +; RUN: llc -mattr=+sme -force-streaming-compatible < %s | FileCheck %s target triple = "aarch64-unknown-linux-gnu" diff --git a/llvm/test/Transforms/InterleavedAccess/AArch64/fixed-deinterleave-intrinsics.ll b/llvm/test/Transforms/InterleavedAccess/AArch64/fixed-deinterleave-intrinsics.ll index 54348d1e2a48..24d624c221f4 100644 --- a/llvm/test/Transforms/InterleavedAccess/AArch64/fixed-deinterleave-intrinsics.ll +++ b/llvm/test/Transforms/InterleavedAccess/AArch64/fixed-deinterleave-intrinsics.ll @@ -1,8 +1,8 @@ ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 2 ; RUN: opt < %s -interleaved-access -S | FileCheck %s --check-prefix=NEON -; RUN: opt < %s -interleaved-access -mtriple=aarch64-linux-gnu -mattr=+sve -force-streaming-compatible-sve -S | FileCheck %s --check-prefix=SVE-FIXED +; RUN: opt < %s -interleaved-access -mtriple=aarch64-linux-gnu -mattr=+sve -force-streaming-compatible -S | FileCheck %s --check-prefix=SVE-FIXED ; RUN: opt < %s -passes=interleaved-access -S | FileCheck %s --check-prefix=NEON -; RUN: opt < %s -passes=interleaved-access -mtriple=aarch64-linux-gnu -mattr=+sve -force-streaming-compatible-sve -S | FileCheck %s --check-prefix=SVE-FIXED +; RUN: opt < %s -passes=interleaved-access -mtriple=aarch64-linux-gnu -mattr=+sve -force-streaming-compatible -S | FileCheck %s --check-prefix=SVE-FIXED target triple = "aarch64-linux-gnu" diff --git a/llvm/test/Transforms/LoopVectorize/AArch64/streaming-compatible-sve-no-maximize-bandwidth.ll b/llvm/test/Transforms/LoopVectorize/AArch64/streaming-compatible-sve-no-maximize-bandwidth.ll index b89d09f25896..6b10d4591f41 100644 --- a/llvm/test/Transforms/LoopVectorize/AArch64/streaming-compatible-sve-no-maximize-bandwidth.ll +++ b/llvm/test/Transforms/LoopVectorize/AArch64/streaming-compatible-sve-no-maximize-bandwidth.ll @@ -1,5 +1,5 @@ ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py -; RUN: opt < %s -passes=loop-vectorize -force-streaming-compatible-sve -enable-fixedwidth-autovec-in-streaming-mode -mattr=+sve -force-target-instruction-cost=1 -scalable-vectorization=off -force-vector-interleave=1 -S 2>&1 | FileCheck %s --check-prefix=SC_SVE +; RUN: opt < %s -passes=loop-vectorize -force-streaming-compatible -enable-fixedwidth-autovec-in-streaming-mode -mattr=+sve -force-target-instruction-cost=1 -scalable-vectorization=off -force-vector-interleave=1 -S 2>&1 | FileCheck %s --check-prefix=SC_SVE ; RUN: opt < %s -passes=loop-vectorize -mattr=+sve -force-target-instruction-cost=1 -scalable-vectorization=off -force-vector-interleave=1 -S 2>&1 | FileCheck %s --check-prefix=NO_SC_SVE target datalayout = "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128" diff --git a/llvm/test/Transforms/ScalarizeMaskedMemIntrin/AArch64/streaming-compatible-expand-masked-gather-scatter.ll b/llvm/test/Transforms/ScalarizeMaskedMemIntrin/AArch64/streaming-compatible-expand-masked-gather-scatter.ll index ee67ab341117..b827fc63c0ef 100644 --- a/llvm/test/Transforms/ScalarizeMaskedMemIntrin/AArch64/streaming-compatible-expand-masked-gather-scatter.ll +++ b/llvm/test/Transforms/ScalarizeMaskedMemIntrin/AArch64/streaming-compatible-expand-masked-gather-scatter.ll @@ -1,6 +1,6 @@ ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py ; REQUIRES: aarch64-registered-target -; RUN: opt -S %s -passes=scalarize-masked-mem-intrin -mtriple=aarch64-linux-gnu -mattr=+sve -force-streaming-compatible-sve | FileCheck %s +; RUN: opt -S %s -passes=scalarize-masked-mem-intrin -mtriple=aarch64-linux-gnu -mattr=+sve -force-streaming-compatible | FileCheck %s define <2 x i32> @scalarize_v2i32(<2 x ptr> %p, <2 x i1> %mask, <2 x i32> %passthru) { ; CHECK-LABEL: @scalarize_v2i32( -- GitLab From 2034f2fc8729bd4645ef7caa3c5c6efa284d2d3f Mon Sep 17 00:00:00 2001 From: Felix Schneider Date: Wed, 22 May 2024 09:02:31 +0200 Subject: [PATCH 079/452] [mlir][intrange] Use `nsw`,`nuw` flags in inference (#92642) This patch includes the "no signed wrap" and "no unsigned wrap" flags, which can be used to annotate some Ops in the `arith` dialect and also in LLVMIR, in the integer range inference. The general approach is to use saturating arithmetic operations to infer bounds which are assumed to not wrap and use overflowing arithmetic operations in the normal case. If overflow is detected in the normal case, special handling makes sure that we don't underestimate the result range. --- .../Interfaces/Utils/InferIntRangeCommon.h | 25 +++- .../Arith/IR/InferIntRangeInterfaceImpls.cpp | 22 ++- .../Index/IR/InferIntRangeInterfaceImpls.cpp | 22 ++- .../Interfaces/Utils/InferIntRangeCommon.cpp | 99 +++++++------ .../Dialect/Arith/int-range-interface.mlir | 133 ++++++++++++++++++ mlir/test/Dialect/Arith/int-range-opts.mlir | 2 +- 6 files changed, 250 insertions(+), 53 deletions(-) diff --git a/mlir/include/mlir/Interfaces/Utils/InferIntRangeCommon.h b/mlir/include/mlir/Interfaces/Utils/InferIntRangeCommon.h index 97c97c23ba82..851bb534bc7e 100644 --- a/mlir/include/mlir/Interfaces/Utils/InferIntRangeCommon.h +++ b/mlir/include/mlir/Interfaces/Utils/InferIntRangeCommon.h @@ -16,6 +16,7 @@ #include "mlir/Interfaces/InferIntRangeInterface.h" #include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/BitmaskEnum.h" #include namespace mlir { @@ -31,6 +32,18 @@ static constexpr unsigned indexMaxWidth = 64; enum class CmpMode : uint32_t { Both, Signed, Unsigned }; +enum class OverflowFlags : uint32_t { + None = 0, + Nsw = 1, + Nuw = 2, + LLVM_MARK_AS_BITMASK_ENUM(Nuw) +}; + +/// Function that performs inference on an array of `ConstantIntRanges` while +/// taking special overflow behavior into account. +using InferRangeWithOvfFlagsFn = + function_ref, OverflowFlags)>; + /// Compute `inferFn` on `ranges`, whose size should be the index storage /// bitwidth. Then, compute the function on `argRanges` again after truncating /// the ranges to 32 bits. Finally, if the truncation of the 64-bit result is @@ -60,11 +73,14 @@ ConstantIntRanges extSIRange(const ConstantIntRanges &range, ConstantIntRanges truncRange(const ConstantIntRanges &range, unsigned destWidth); -ConstantIntRanges inferAdd(ArrayRef argRanges); +ConstantIntRanges inferAdd(ArrayRef argRanges, + OverflowFlags ovfFlags = OverflowFlags::None); -ConstantIntRanges inferSub(ArrayRef argRanges); +ConstantIntRanges inferSub(ArrayRef argRanges, + OverflowFlags ovfFlags = OverflowFlags::None); -ConstantIntRanges inferMul(ArrayRef argRanges); +ConstantIntRanges inferMul(ArrayRef argRanges, + OverflowFlags ovfFlags = OverflowFlags::None); ConstantIntRanges inferDivS(ArrayRef argRanges); @@ -94,7 +110,8 @@ ConstantIntRanges inferOr(ArrayRef argRanges); ConstantIntRanges inferXor(ArrayRef argRanges); -ConstantIntRanges inferShl(ArrayRef argRanges); +ConstantIntRanges inferShl(ArrayRef argRanges, + OverflowFlags ovfFlags = OverflowFlags::None); ConstantIntRanges inferShrS(ArrayRef argRanges); diff --git a/mlir/lib/Dialect/Arith/IR/InferIntRangeInterfaceImpls.cpp b/mlir/lib/Dialect/Arith/IR/InferIntRangeInterfaceImpls.cpp index 71eb36bb07a6..fbe2ecab8adc 100644 --- a/mlir/lib/Dialect/Arith/IR/InferIntRangeInterfaceImpls.cpp +++ b/mlir/lib/Dialect/Arith/IR/InferIntRangeInterfaceImpls.cpp @@ -19,6 +19,16 @@ using namespace mlir; using namespace mlir::arith; using namespace mlir::intrange; +static intrange::OverflowFlags +convertArithOverflowFlags(arith::IntegerOverflowFlags flags) { + intrange::OverflowFlags retFlags = intrange::OverflowFlags::None; + if (bitEnumContainsAny(flags, arith::IntegerOverflowFlags::nsw)) + retFlags |= intrange::OverflowFlags::Nsw; + if (bitEnumContainsAny(flags, arith::IntegerOverflowFlags::nuw)) + retFlags |= intrange::OverflowFlags::Nuw; + return retFlags; +} + //===----------------------------------------------------------------------===// // ConstantOp //===----------------------------------------------------------------------===// @@ -38,7 +48,8 @@ void arith::ConstantOp::inferResultRanges(ArrayRef argRanges, void arith::AddIOp::inferResultRanges(ArrayRef argRanges, SetIntRangeFn setResultRange) { - setResultRange(getResult(), inferAdd(argRanges)); + setResultRange(getResult(), inferAdd(argRanges, convertArithOverflowFlags( + getOverflowFlags()))); } //===----------------------------------------------------------------------===// @@ -47,7 +58,8 @@ void arith::AddIOp::inferResultRanges(ArrayRef argRanges, void arith::SubIOp::inferResultRanges(ArrayRef argRanges, SetIntRangeFn setResultRange) { - setResultRange(getResult(), inferSub(argRanges)); + setResultRange(getResult(), inferSub(argRanges, convertArithOverflowFlags( + getOverflowFlags()))); } //===----------------------------------------------------------------------===// @@ -56,7 +68,8 @@ void arith::SubIOp::inferResultRanges(ArrayRef argRanges, void arith::MulIOp::inferResultRanges(ArrayRef argRanges, SetIntRangeFn setResultRange) { - setResultRange(getResult(), inferMul(argRanges)); + setResultRange(getResult(), inferMul(argRanges, convertArithOverflowFlags( + getOverflowFlags()))); } //===----------------------------------------------------------------------===// @@ -302,7 +315,8 @@ void arith::SelectOp::inferResultRanges(ArrayRef argRanges, void arith::ShLIOp::inferResultRanges(ArrayRef argRanges, SetIntRangeFn setResultRange) { - setResultRange(getResult(), inferShl(argRanges)); + setResultRange(getResult(), inferShl(argRanges, convertArithOverflowFlags( + getOverflowFlags()))); } //===----------------------------------------------------------------------===// diff --git a/mlir/lib/Dialect/Index/IR/InferIntRangeInterfaceImpls.cpp b/mlir/lib/Dialect/Index/IR/InferIntRangeInterfaceImpls.cpp index b6b8a136791c..64adb6b85052 100644 --- a/mlir/lib/Dialect/Index/IR/InferIntRangeInterfaceImpls.cpp +++ b/mlir/lib/Dialect/Index/IR/InferIntRangeInterfaceImpls.cpp @@ -44,19 +44,32 @@ void BoolConstantOp::inferResultRanges(ArrayRef argRanges, // we take the 64-bit result). //===----------------------------------------------------------------------===// +// Some arithmetic inference functions allow specifying special overflow / wrap +// behavior. We do not require this for the IndexOps and use this helper to call +// the inference function without any `OverflowFlags`. +static std::function)> +inferWithoutOverflowFlags(InferRangeWithOvfFlagsFn inferWithOvfFn) { + return [inferWithOvfFn](ArrayRef argRanges) { + return inferWithOvfFn(argRanges, OverflowFlags::None); + }; +} + void AddOp::inferResultRanges(ArrayRef argRanges, SetIntRangeFn setResultRange) { - setResultRange(getResult(), inferIndexOp(inferAdd, argRanges, CmpMode::Both)); + setResultRange(getResult(), inferIndexOp(inferWithoutOverflowFlags(inferAdd), + argRanges, CmpMode::Both)); } void SubOp::inferResultRanges(ArrayRef argRanges, SetIntRangeFn setResultRange) { - setResultRange(getResult(), inferIndexOp(inferSub, argRanges, CmpMode::Both)); + setResultRange(getResult(), inferIndexOp(inferWithoutOverflowFlags(inferSub), + argRanges, CmpMode::Both)); } void MulOp::inferResultRanges(ArrayRef argRanges, SetIntRangeFn setResultRange) { - setResultRange(getResult(), inferIndexOp(inferMul, argRanges, CmpMode::Both)); + setResultRange(getResult(), inferIndexOp(inferWithoutOverflowFlags(inferMul), + argRanges, CmpMode::Both)); } void DivUOp::inferResultRanges(ArrayRef argRanges, @@ -127,7 +140,8 @@ void MinUOp::inferResultRanges(ArrayRef argRanges, void ShlOp::inferResultRanges(ArrayRef argRanges, SetIntRangeFn setResultRange) { - setResultRange(getResult(), inferIndexOp(inferShl, argRanges, CmpMode::Both)); + setResultRange(getResult(), inferIndexOp(inferWithoutOverflowFlags(inferShl), + argRanges, CmpMode::Both)); } void ShrSOp::inferResultRanges(ArrayRef argRanges, diff --git a/mlir/lib/Interfaces/Utils/InferIntRangeCommon.cpp b/mlir/lib/Interfaces/Utils/InferIntRangeCommon.cpp index 6af229cae10a..fe1a67d62873 100644 --- a/mlir/lib/Interfaces/Utils/InferIntRangeCommon.cpp +++ b/mlir/lib/Interfaces/Utils/InferIntRangeCommon.cpp @@ -178,18 +178,24 @@ ConstantIntRanges mlir::intrange::truncRange(const ConstantIntRanges &range, //===----------------------------------------------------------------------===// ConstantIntRanges -mlir::intrange::inferAdd(ArrayRef argRanges) { +mlir::intrange::inferAdd(ArrayRef argRanges, + OverflowFlags ovfFlags) { const ConstantIntRanges &lhs = argRanges[0], &rhs = argRanges[1]; - ConstArithFn uadd = [](const APInt &a, - const APInt &b) -> std::optional { + + std::function uadd = [=](const APInt &a, + const APInt &b) -> std::optional { bool overflowed = false; - APInt result = a.uadd_ov(b, overflowed); + APInt result = any(ovfFlags & OverflowFlags::Nuw) + ? a.uadd_sat(b) + : a.uadd_ov(b, overflowed); return overflowed ? std::optional() : result; }; - ConstArithFn sadd = [](const APInt &a, - const APInt &b) -> std::optional { + std::function sadd = [=](const APInt &a, + const APInt &b) -> std::optional { bool overflowed = false; - APInt result = a.sadd_ov(b, overflowed); + APInt result = any(ovfFlags & OverflowFlags::Nsw) + ? a.sadd_sat(b) + : a.sadd_ov(b, overflowed); return overflowed ? std::optional() : result; }; @@ -205,19 +211,24 @@ mlir::intrange::inferAdd(ArrayRef argRanges) { //===----------------------------------------------------------------------===// ConstantIntRanges -mlir::intrange::inferSub(ArrayRef argRanges) { +mlir::intrange::inferSub(ArrayRef argRanges, + OverflowFlags ovfFlags) { const ConstantIntRanges &lhs = argRanges[0], &rhs = argRanges[1]; - ConstArithFn usub = [](const APInt &a, - const APInt &b) -> std::optional { + std::function usub = [=](const APInt &a, + const APInt &b) -> std::optional { bool overflowed = false; - APInt result = a.usub_ov(b, overflowed); + APInt result = any(ovfFlags & OverflowFlags::Nuw) + ? a.usub_sat(b) + : a.usub_ov(b, overflowed); return overflowed ? std::optional() : result; }; - ConstArithFn ssub = [](const APInt &a, - const APInt &b) -> std::optional { + std::function ssub = [=](const APInt &a, + const APInt &b) -> std::optional { bool overflowed = false; - APInt result = a.ssub_ov(b, overflowed); + APInt result = any(ovfFlags & OverflowFlags::Nsw) + ? a.ssub_sat(b) + : a.ssub_ov(b, overflowed); return overflowed ? std::optional() : result; }; ConstantIntRanges urange = computeBoundsBy( @@ -232,19 +243,24 @@ mlir::intrange::inferSub(ArrayRef argRanges) { //===----------------------------------------------------------------------===// ConstantIntRanges -mlir::intrange::inferMul(ArrayRef argRanges) { +mlir::intrange::inferMul(ArrayRef argRanges, + OverflowFlags ovfFlags) { const ConstantIntRanges &lhs = argRanges[0], &rhs = argRanges[1]; - ConstArithFn umul = [](const APInt &a, - const APInt &b) -> std::optional { + std::function umul = [=](const APInt &a, + const APInt &b) -> std::optional { bool overflowed = false; - APInt result = a.umul_ov(b, overflowed); + APInt result = any(ovfFlags & OverflowFlags::Nuw) + ? a.umul_sat(b) + : a.umul_ov(b, overflowed); return overflowed ? std::optional() : result; }; - ConstArithFn smul = [](const APInt &a, - const APInt &b) -> std::optional { + std::function smul = [=](const APInt &a, + const APInt &b) -> std::optional { bool overflowed = false; - APInt result = a.smul_ov(b, overflowed); + APInt result = any(ovfFlags & OverflowFlags::Nsw) + ? a.smul_sat(b) + : a.smul_ov(b, overflowed); return overflowed ? std::optional() : result; }; @@ -542,32 +558,35 @@ mlir::intrange::inferXor(ArrayRef argRanges) { //===----------------------------------------------------------------------===// ConstantIntRanges -mlir::intrange::inferShl(ArrayRef argRanges) { +mlir::intrange::inferShl(ArrayRef argRanges, + OverflowFlags ovfFlags) { const ConstantIntRanges &lhs = argRanges[0], &rhs = argRanges[1]; - const APInt &lhsSMin = lhs.smin(), &lhsSMax = lhs.smax(), - &lhsUMax = lhs.umax(), &rhsUMin = rhs.umin(), - &rhsUMax = rhs.umax(); + const APInt &rhsUMin = rhs.umin(), &rhsUMax = rhs.umax(); - ConstArithFn shl = [](const APInt &l, - const APInt &r) -> std::optional { - return r.uge(r.getBitWidth()) ? std::optional() : l.shl(r); + // The signed/unsigned overflow behavior of shl by `rhs` matches a mul with + // 2^rhs. + std::function ushl = [=](const APInt &l, + const APInt &r) -> std::optional { + bool overflowed = false; + APInt result = any(ovfFlags & OverflowFlags::Nuw) + ? l.ushl_sat(r) + : l.ushl_ov(r, overflowed); + return overflowed ? std::optional() : result; + }; + std::function sshl = [=](const APInt &l, + const APInt &r) -> std::optional { + bool overflowed = false; + APInt result = any(ovfFlags & OverflowFlags::Nsw) + ? l.sshl_sat(r) + : l.sshl_ov(r, overflowed); + return overflowed ? std::optional() : result; }; - - // The minMax inference does not work when there is danger of overflow. In the - // signed case, this leads to the obvious problem that the sign bit might - // change. In the unsigned case, it also leads to problems because the largest - // LHS shifted by the largest RHS does not necessarily result in the largest - // result anymore. - assert(rhsUMax.isNonNegative() && "Unexpected negative shift count"); - if (rhsUMax.uge(lhsSMin.getNumSignBits()) || - rhsUMax.uge(lhsSMax.getNumSignBits())) - return ConstantIntRanges::maxRange(lhsUMax.getBitWidth()); ConstantIntRanges urange = - minMaxBy(shl, {lhs.umin(), lhsUMax}, {rhsUMin, rhsUMax}, + minMaxBy(ushl, {lhs.umin(), lhs.umax()}, {rhsUMin, rhsUMax}, /*isSigned=*/false); ConstantIntRanges srange = - minMaxBy(shl, {lhsSMin, lhsSMax}, {rhsUMin, rhsUMax}, + minMaxBy(sshl, {lhs.smin(), lhs.smax()}, {rhsUMin, rhsUMax}, /*isSigned=*/true); return urange.intersection(srange); } diff --git a/mlir/test/Dialect/Arith/int-range-interface.mlir b/mlir/test/Dialect/Arith/int-range-interface.mlir index 17d3fcfc13ce..5b538197a0c1 100644 --- a/mlir/test/Dialect/Arith/int-range-interface.mlir +++ b/mlir/test/Dialect/Arith/int-range-interface.mlir @@ -766,3 +766,136 @@ func.func @test_i8_bounds() -> i8 { %2 = test.reflect_bounds %1 : i8 return %2: i8 } + +// CHECK-LABEL: func @test_add_1 +// CHECK: test.reflect_bounds {smax = 127 : si8, smin = -128 : si8, umax = 255 : ui8, umin = 0 : ui8} +func.func @test_add_1() -> i8 { + %cst1 = arith.constant 1 : i8 + %0 = test.with_bounds { umin = 0 : i8, umax = 255 : i8, smin = -128 : i8, smax = 127 : i8 } : i8 + %1 = arith.addi %0, %cst1 : i8 + %2 = test.reflect_bounds %1 : i8 + return %2: i8 +} + +// Tests below check inference with overflow flags. + +// CHECK-LABEL: func @test_add_i8_wrap1 +// CHECK: test.reflect_bounds {smax = 127 : si8, smin = -128 : si8, umax = 128 : ui8, umin = 1 : ui8} +func.func @test_add_i8_wrap1() -> i8 { + %cst1 = arith.constant 1 : i8 + %0 = test.with_bounds { umin = 0 : i8, umax = 127 : i8, smin = 0 : i8, smax = 127 : i8 } : i8 + // smax overflow + %1 = arith.addi %0, %cst1 : i8 + %2 = test.reflect_bounds %1 : i8 + return %2: i8 +} + +// CHECK-LABEL: func @test_add_i8_wrap2 +// CHECK: test.reflect_bounds {smax = 127 : si8, smin = -128 : si8, umax = 128 : ui8, umin = 1 : ui8} +func.func @test_add_i8_wrap2() -> i8 { + %cst1 = arith.constant 1 : i8 + %0 = test.with_bounds { umin = 0 : i8, umax = 127 : i8, smin = 0 : i8, smax = 127 : i8 } : i8 + // smax overflow + %1 = arith.addi %0, %cst1 overflow : i8 + %2 = test.reflect_bounds %1 : i8 + return %2: i8 +} + +// CHECK-LABEL: func @test_add_i8_nowrap +// CHECK: test.reflect_bounds {smax = 127 : si8, smin = 1 : si8, umax = 127 : ui8, umin = 1 : ui8} +func.func @test_add_i8_nowrap() -> i8 { + %cst1 = arith.constant 1 : i8 + %0 = test.with_bounds { umin = 0 : i8, umax = 127 : i8, smin = 0 : i8, smax = 127 : i8 } : i8 + // nsw flag stops smax from overflowing + %1 = arith.addi %0, %cst1 overflow : i8 + %2 = test.reflect_bounds %1 : i8 + return %2: i8 +} + +// CHECK-LABEL: func @test_sub_i8_wrap1 +// CHECK: test.reflect_bounds {smax = 5 : si8, smin = -10 : si8, umax = 255 : ui8, umin = 0 : ui8} %1 : i8 +func.func @test_sub_i8_wrap1() -> i8 { + %cst10 = arith.constant 10 : i8 + %0 = test.with_bounds { umin = 0 : i8, umax = 15 : i8, smin = 0 : i8, smax = 15 : i8 } : i8 + // umin underflows + %1 = arith.subi %0, %cst10 : i8 + %2 = test.reflect_bounds %1 : i8 + return %2: i8 +} + +// CHECK-LABEL: func @test_sub_i8_wrap2 +// CHECK: test.reflect_bounds {smax = 5 : si8, smin = -10 : si8, umax = 255 : ui8, umin = 0 : ui8} %1 : i8 +func.func @test_sub_i8_wrap2() -> i8 { + %cst10 = arith.constant 10 : i8 + %0 = test.with_bounds { umin = 0 : i8, umax = 15 : i8, smin = 0 : i8, smax = 15 : i8 } : i8 + // umin underflows + %1 = arith.subi %0, %cst10 overflow : i8 + %2 = test.reflect_bounds %1 : i8 + return %2: i8 +} + +// CHECK-LABEL: func @test_sub_i8_nowrap +// CHECK: test.reflect_bounds {smax = 5 : si8, smin = 0 : si8, umax = 5 : ui8, umin = 0 : ui8} +func.func @test_sub_i8_nowrap() -> i8 { + %cst10 = arith.constant 10 : i8 + %0 = test.with_bounds { umin = 0 : i8, umax = 15 : i8, smin = 0 : i8, smax = 15 : i8 } : i8 + // nuw flag stops umin from underflowing + %1 = arith.subi %0, %cst10 overflow : i8 + %2 = test.reflect_bounds %1 : i8 + return %2: i8 +} + +// CHECK-LABEL: func @test_mul_i8_wrap +// CHECK: test.reflect_bounds {smax = 127 : si8, smin = -128 : si8, umax = 200 : ui8, umin = 100 : ui8} +func.func @test_mul_i8_wrap() -> i8 { + %cst10 = arith.constant 10 : i8 + %0 = test.with_bounds { umin = 10 : i8, umax = 20 : i8, smin = 10 : i8, smax = 20 : i8 } : i8 + // smax overflows + %1 = arith.muli %0, %cst10 : i8 + %2 = test.reflect_bounds %1 : i8 + return %2: i8 +} + +// CHECK-LABEL: func @test_mul_i8_nowrap +// CHECK: test.reflect_bounds {smax = 127 : si8, smin = 100 : si8, umax = 127 : ui8, umin = 100 : ui8} +func.func @test_mul_i8_nowrap() -> i8 { + %cst10 = arith.constant 10 : i8 + %0 = test.with_bounds { umin = 10 : i8, umax = 20 : i8, smin = 10 : i8, smax = 20 : i8 } : i8 + // nsw stops overflow + %1 = arith.muli %0, %cst10 overflow : i8 + %2 = test.reflect_bounds %1 : i8 + return %2: i8 +} + +// CHECK-LABEL: func @test_shl_i8_wrap1 +// CHECK: test.reflect_bounds {smax = 127 : si8, smin = -128 : si8, umax = 160 : ui8, umin = 80 : ui8} +func.func @test_shl_i8_wrap1() -> i8 { + %cst3 = arith.constant 3 : i8 + %0 = test.with_bounds { umin = 10 : i8, umax = 20 : i8, smin = 10 : i8, smax = 20 : i8 } : i8 + // smax overflows + %1 = arith.shli %0, %cst3 : i8 + %2 = test.reflect_bounds %1 : i8 + return %2: i8 +} + +// CHECK-LABEL: func @test_shl_i8_wrap2 +// CHECK: test.reflect_bounds {smax = 127 : si8, smin = -128 : si8, umax = 160 : ui8, umin = 80 : ui8} +func.func @test_shl_i8_wrap2() -> i8 { + %cst3 = arith.constant 3 : i8 + %0 = test.with_bounds { umin = 10 : i8, umax = 20 : i8, smin = 10 : i8, smax = 20 : i8 } : i8 + // smax overflows + %1 = arith.shli %0, %cst3 overflow : i8 + %2 = test.reflect_bounds %1 : i8 + return %2: i8 +} + +// CHECK-LABEL: func @test_shl_i8_nowrap +// CHECK: test.reflect_bounds {smax = 127 : si8, smin = 80 : si8, umax = 127 : ui8, umin = 80 : ui8} +func.func @test_shl_i8_nowrap() -> i8 { + %cst3 = arith.constant 3 : i8 + %0 = test.with_bounds { umin = 10 : i8, umax = 20 : ui8, smin = 10 : i8, smax = 20 : i8 } : i8 + // nsw stops smax overflow + %1 = arith.shli %0, %cst3 overflow : i8 + %2 = test.reflect_bounds %1 : i8 + return %2: i8 +} diff --git a/mlir/test/Dialect/Arith/int-range-opts.mlir b/mlir/test/Dialect/Arith/int-range-opts.mlir index 71174f1c5ef0..dd62a481a124 100644 --- a/mlir/test/Dialect/Arith/int-range-opts.mlir +++ b/mlir/test/Dialect/Arith/int-range-opts.mlir @@ -87,7 +87,7 @@ func.func @test() -> i8 { // ----- // CHECK-LABEL: func @test -// CHECK: test.reflect_bounds {smax = 127 : si8, smin = -128 : si8, umax = 255 : ui8, umin = 0 : ui8} +// CHECK: test.reflect_bounds {smax = 127 : si8, smin = -128 : si8, umax = 254 : ui8, umin = 0 : ui8} func.func @test() -> i8 { %cst1 = arith.constant 1 : i8 %i8val = test.with_bounds { umin = 0 : i8, umax = 127 : i8, smin = 0 : i8, smax = 127 : i8 } : i8 -- GitLab From 235465e40475a3bce1c11b21032844c0c8e14f28 Mon Sep 17 00:00:00 2001 From: Yingwei Zheng Date: Wed, 22 May 2024 15:18:15 +0800 Subject: [PATCH 080/452] [RISCV][GISel] Legalize G_{U|S}{ADD|SUB}SAT (#92935) This patch adds support for G_UADDSAT/G_SADDSAT/G_USUBSAT/G_SSUBSAT by lowering it into add/sub with selects. When zbb is available, min/max/minu/maxu will be selected. --- .../Target/RISCV/GISel/RISCVLegalizerInfo.cpp | 4 + .../legalizer/legalize-sat-rv32.mir | 404 ++++++++++++++++++ .../legalizer/legalize-sat-rv64.mir | 358 ++++++++++++++++ 3 files changed, 766 insertions(+) create mode 100644 llvm/test/CodeGen/RISCV/GlobalISel/legalizer/legalize-sat-rv32.mir create mode 100644 llvm/test/CodeGen/RISCV/GlobalISel/legalizer/legalize-sat-rv64.mir diff --git a/llvm/lib/Target/RISCV/GISel/RISCVLegalizerInfo.cpp b/llvm/lib/Target/RISCV/GISel/RISCVLegalizerInfo.cpp index c73fe2c6cecb..e3d74cef7e7f 100644 --- a/llvm/lib/Target/RISCV/GISel/RISCVLegalizerInfo.cpp +++ b/llvm/lib/Target/RISCV/GISel/RISCVLegalizerInfo.cpp @@ -130,6 +130,10 @@ RISCVLegalizerInfo::RISCVLegalizerInfo(const RISCVSubtarget &ST) getActionDefinitionsBuilder({G_SADDO, G_SSUBO}).minScalar(0, sXLen).lower(); + // TODO: Use Vector Single-Width Saturating Instructions for vector types. + getActionDefinitionsBuilder({G_UADDSAT, G_SADDSAT, G_USUBSAT, G_SSUBSAT}) + .lower(); + auto &ShiftActions = getActionDefinitionsBuilder({G_ASHR, G_LSHR, G_SHL}); if (ST.is64Bit()) ShiftActions.customFor({{s32, s32}}); diff --git a/llvm/test/CodeGen/RISCV/GlobalISel/legalizer/legalize-sat-rv32.mir b/llvm/test/CodeGen/RISCV/GlobalISel/legalizer/legalize-sat-rv32.mir new file mode 100644 index 000000000000..08aa92e0207b --- /dev/null +++ b/llvm/test/CodeGen/RISCV/GlobalISel/legalizer/legalize-sat-rv32.mir @@ -0,0 +1,404 @@ +# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py UTC_ARGS: --version 5 +# RUN: llc -mtriple=riscv32 -run-pass=legalizer %s -o - \ +# RUN: | FileCheck %s --check-prefixes=CHECK,RV32I +# RUN: llc -mtriple=riscv32 -mattr=+zbb -run-pass=legalizer %s -o - \ +# RUN: | FileCheck %s --check-prefixes=CHECK,RV32ZBB + +--- +name: uaddsat_i32 +body: | + bb.1: + liveins: $x10, $x11 + + ; RV32I-LABEL: name: uaddsat_i32 + ; RV32I: liveins: $x10, $x11 + ; RV32I-NEXT: {{ $}} + ; RV32I-NEXT: [[COPY:%[0-9]+]]:_(s32) = COPY $x10 + ; RV32I-NEXT: [[COPY1:%[0-9]+]]:_(s32) = COPY $x11 + ; RV32I-NEXT: [[ADD:%[0-9]+]]:_(s32) = G_ADD [[COPY]], [[COPY1]] + ; RV32I-NEXT: [[ICMP:%[0-9]+]]:_(s32) = G_ICMP intpred(ult), [[ADD]](s32), [[COPY1]] + ; RV32I-NEXT: [[COPY2:%[0-9]+]]:_(s32) = COPY [[ADD]](s32) + ; RV32I-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 -1 + ; RV32I-NEXT: [[SELECT:%[0-9]+]]:_(s32) = G_SELECT [[ICMP]](s32), [[C]], [[COPY2]] + ; RV32I-NEXT: $x10 = COPY [[SELECT]](s32) + ; RV32I-NEXT: PseudoRET implicit $x10 + ; + ; RV32ZBB-LABEL: name: uaddsat_i32 + ; RV32ZBB: liveins: $x10, $x11 + ; RV32ZBB-NEXT: {{ $}} + ; RV32ZBB-NEXT: [[COPY:%[0-9]+]]:_(s32) = COPY $x10 + ; RV32ZBB-NEXT: [[COPY1:%[0-9]+]]:_(s32) = COPY $x11 + ; RV32ZBB-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 -1 + ; RV32ZBB-NEXT: [[XOR:%[0-9]+]]:_(s32) = G_XOR [[COPY]], [[C]] + ; RV32ZBB-NEXT: [[UMIN:%[0-9]+]]:_(s32) = G_UMIN [[XOR]], [[COPY1]] + ; RV32ZBB-NEXT: [[ADD:%[0-9]+]]:_(s32) = G_ADD [[COPY]], [[UMIN]] + ; RV32ZBB-NEXT: $x10 = COPY [[ADD]](s32) + ; RV32ZBB-NEXT: PseudoRET implicit $x10 + %0:_(s32) = COPY $x10 + %1:_(s32) = COPY $x11 + %2:_(s32) = G_UADDSAT %0, %1(s32) + $x10 = COPY %2(s32) + PseudoRET implicit $x10 + +... +--- +name: uaddsat_i64 +body: | + bb.1: + liveins: $x10, $x11 + ; CHECK-LABEL: name: uaddsat_i64 + ; CHECK: liveins: $x10, $x11 + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: [[COPY:%[0-9]+]]:_(s32) = COPY $x10 + ; CHECK-NEXT: [[COPY1:%[0-9]+]]:_(s32) = COPY $x11 + ; CHECK-NEXT: [[COPY2:%[0-9]+]]:_(s32) = COPY $x12 + ; CHECK-NEXT: [[COPY3:%[0-9]+]]:_(s32) = COPY $x13 + ; CHECK-NEXT: [[ADD:%[0-9]+]]:_(s32) = G_ADD [[COPY]], [[COPY2]] + ; CHECK-NEXT: [[ICMP:%[0-9]+]]:_(s32) = G_ICMP intpred(ult), [[ADD]](s32), [[COPY2]] + ; CHECK-NEXT: [[COPY4:%[0-9]+]]:_(s32) = COPY [[ADD]](s32) + ; CHECK-NEXT: [[ADD1:%[0-9]+]]:_(s32) = G_ADD [[COPY1]], [[COPY3]] + ; CHECK-NEXT: [[ADD2:%[0-9]+]]:_(s32) = G_ADD [[ADD1]], [[ICMP]] + ; CHECK-NEXT: [[COPY5:%[0-9]+]]:_(s32) = COPY [[ADD2]](s32) + ; CHECK-NEXT: [[ICMP1:%[0-9]+]]:_(s32) = G_ICMP intpred(ult), [[COPY5]](s32), [[COPY3]] + ; CHECK-NEXT: [[ICMP2:%[0-9]+]]:_(s32) = G_ICMP intpred(eq), [[COPY5]](s32), [[COPY3]] + ; CHECK-NEXT: [[ICMP3:%[0-9]+]]:_(s32) = G_ICMP intpred(ult), [[COPY4]](s32), [[COPY2]] + ; CHECK-NEXT: [[SELECT:%[0-9]+]]:_(s32) = G_SELECT [[ICMP2]](s32), [[ICMP3]], [[ICMP1]] + ; CHECK-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 -1 + ; CHECK-NEXT: [[C1:%[0-9]+]]:_(s32) = G_CONSTANT i32 -1 + ; CHECK-NEXT: [[SELECT1:%[0-9]+]]:_(s32) = G_SELECT [[SELECT]](s32), [[C]], [[COPY4]] + ; CHECK-NEXT: [[SELECT2:%[0-9]+]]:_(s32) = G_SELECT [[SELECT]](s32), [[C1]], [[COPY5]] + ; CHECK-NEXT: $x10 = COPY [[SELECT1]](s32) + ; CHECK-NEXT: $x11 = COPY [[SELECT2]](s32) + ; CHECK-NEXT: PseudoRET implicit $x10, implicit $x11 + %2:_(s32) = COPY $x10 + %3:_(s32) = COPY $x11 + %0:_(s64) = G_MERGE_VALUES %2(s32), %3(s32) + %4:_(s32) = COPY $x12 + %5:_(s32) = COPY $x13 + %1:_(s64) = G_MERGE_VALUES %4(s32), %5(s32) + %6:_(s64) = G_UADDSAT %0, %1(s64) + %7:_(s32), %8:_(s32) = G_UNMERGE_VALUES %6(s64) + $x10 = COPY %7(s32) + $x11 = COPY %8(s32) + PseudoRET implicit $x10, implicit $x11 + +... +--- +name: saddsat_i32 +body: | + bb.1: + liveins: $x10, $x11 + + ; RV32I-LABEL: name: saddsat_i32 + ; RV32I: liveins: $x10, $x11 + ; RV32I-NEXT: {{ $}} + ; RV32I-NEXT: [[COPY:%[0-9]+]]:_(s32) = COPY $x10 + ; RV32I-NEXT: [[COPY1:%[0-9]+]]:_(s32) = COPY $x11 + ; RV32I-NEXT: [[ADD:%[0-9]+]]:_(s32) = G_ADD [[COPY]], [[COPY1]] + ; RV32I-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 0 + ; RV32I-NEXT: [[ICMP:%[0-9]+]]:_(s32) = G_ICMP intpred(slt), [[ADD]](s32), [[COPY]] + ; RV32I-NEXT: [[ICMP1:%[0-9]+]]:_(s32) = G_ICMP intpred(slt), [[COPY1]](s32), [[C]] + ; RV32I-NEXT: [[XOR:%[0-9]+]]:_(s32) = G_XOR [[ICMP1]], [[ICMP]] + ; RV32I-NEXT: [[COPY2:%[0-9]+]]:_(s32) = COPY [[ADD]](s32) + ; RV32I-NEXT: [[C1:%[0-9]+]]:_(s32) = G_CONSTANT i32 31 + ; RV32I-NEXT: [[ASHR:%[0-9]+]]:_(s32) = G_ASHR [[COPY2]], [[C1]](s32) + ; RV32I-NEXT: [[C2:%[0-9]+]]:_(s32) = G_CONSTANT i32 -2147483648 + ; RV32I-NEXT: [[ADD1:%[0-9]+]]:_(s32) = G_ADD [[ASHR]], [[C2]] + ; RV32I-NEXT: [[SELECT:%[0-9]+]]:_(s32) = G_SELECT [[XOR]](s32), [[ADD1]], [[COPY2]] + ; RV32I-NEXT: $x10 = COPY [[SELECT]](s32) + ; RV32I-NEXT: PseudoRET implicit $x10 + ; + ; RV32ZBB-LABEL: name: saddsat_i32 + ; RV32ZBB: liveins: $x10, $x11 + ; RV32ZBB-NEXT: {{ $}} + ; RV32ZBB-NEXT: [[COPY:%[0-9]+]]:_(s32) = COPY $x10 + ; RV32ZBB-NEXT: [[COPY1:%[0-9]+]]:_(s32) = COPY $x11 + ; RV32ZBB-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 2147483647 + ; RV32ZBB-NEXT: [[C1:%[0-9]+]]:_(s32) = G_CONSTANT i32 -2147483648 + ; RV32ZBB-NEXT: [[C2:%[0-9]+]]:_(s32) = G_CONSTANT i32 0 + ; RV32ZBB-NEXT: [[SMAX:%[0-9]+]]:_(s32) = G_SMAX [[COPY]], [[C2]] + ; RV32ZBB-NEXT: [[SUB:%[0-9]+]]:_(s32) = G_SUB [[C]], [[SMAX]] + ; RV32ZBB-NEXT: [[SMIN:%[0-9]+]]:_(s32) = G_SMIN [[COPY]], [[C2]] + ; RV32ZBB-NEXT: [[SUB1:%[0-9]+]]:_(s32) = G_SUB [[C1]], [[SMIN]] + ; RV32ZBB-NEXT: [[SMAX1:%[0-9]+]]:_(s32) = G_SMAX [[SUB1]], [[COPY1]] + ; RV32ZBB-NEXT: [[SMIN1:%[0-9]+]]:_(s32) = G_SMIN [[SMAX1]], [[SUB]] + ; RV32ZBB-NEXT: [[ADD:%[0-9]+]]:_(s32) = G_ADD [[COPY]], [[SMIN1]] + ; RV32ZBB-NEXT: $x10 = COPY [[ADD]](s32) + ; RV32ZBB-NEXT: PseudoRET implicit $x10 + %0:_(s32) = COPY $x10 + %1:_(s32) = COPY $x11 + %2:_(s32) = G_SADDSAT %0, %1(s32) + $x10 = COPY %2(s32) + PseudoRET implicit $x10 + +... +--- +name: saddsat_i64 +body: | + bb.1: + liveins: $x10, $x11 + ; CHECK-LABEL: name: saddsat_i64 + ; CHECK: liveins: $x10, $x11 + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: [[COPY:%[0-9]+]]:_(s32) = COPY $x10 + ; CHECK-NEXT: [[COPY1:%[0-9]+]]:_(s32) = COPY $x11 + ; CHECK-NEXT: [[COPY2:%[0-9]+]]:_(s32) = COPY $x12 + ; CHECK-NEXT: [[COPY3:%[0-9]+]]:_(s32) = COPY $x13 + ; CHECK-NEXT: [[ADD:%[0-9]+]]:_(s32) = G_ADD [[COPY]], [[COPY2]] + ; CHECK-NEXT: [[ICMP:%[0-9]+]]:_(s32) = G_ICMP intpred(ult), [[ADD]](s32), [[COPY2]] + ; CHECK-NEXT: [[COPY4:%[0-9]+]]:_(s32) = COPY [[ADD]](s32) + ; CHECK-NEXT: [[ADD1:%[0-9]+]]:_(s32) = G_ADD [[COPY1]], [[COPY3]] + ; CHECK-NEXT: [[ADD2:%[0-9]+]]:_(s32) = G_ADD [[ADD1]], [[ICMP]] + ; CHECK-NEXT: [[COPY5:%[0-9]+]]:_(s32) = COPY [[ADD2]](s32) + ; CHECK-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 0 + ; CHECK-NEXT: [[C1:%[0-9]+]]:_(s32) = G_CONSTANT i32 0 + ; CHECK-NEXT: [[ICMP1:%[0-9]+]]:_(s32) = G_ICMP intpred(slt), [[COPY5]](s32), [[COPY1]] + ; CHECK-NEXT: [[ICMP2:%[0-9]+]]:_(s32) = G_ICMP intpred(eq), [[COPY5]](s32), [[COPY1]] + ; CHECK-NEXT: [[ICMP3:%[0-9]+]]:_(s32) = G_ICMP intpred(ult), [[COPY4]](s32), [[COPY]] + ; CHECK-NEXT: [[SELECT:%[0-9]+]]:_(s32) = G_SELECT [[ICMP2]](s32), [[ICMP3]], [[ICMP1]] + ; CHECK-NEXT: [[ICMP4:%[0-9]+]]:_(s32) = G_ICMP intpred(slt), [[COPY3]](s32), [[C1]] + ; CHECK-NEXT: [[ICMP5:%[0-9]+]]:_(s32) = G_ICMP intpred(eq), [[COPY3]](s32), [[C1]] + ; CHECK-NEXT: [[ICMP6:%[0-9]+]]:_(s32) = G_ICMP intpred(ult), [[COPY2]](s32), [[C]] + ; CHECK-NEXT: [[SELECT1:%[0-9]+]]:_(s32) = G_SELECT [[ICMP5]](s32), [[ICMP6]], [[ICMP4]] + ; CHECK-NEXT: [[XOR:%[0-9]+]]:_(s32) = G_XOR [[SELECT1]], [[SELECT]] + ; CHECK-NEXT: [[C2:%[0-9]+]]:_(s32) = G_CONSTANT i32 31 + ; CHECK-NEXT: [[ASHR:%[0-9]+]]:_(s32) = G_ASHR [[COPY5]], [[C2]](s32) + ; CHECK-NEXT: [[C3:%[0-9]+]]:_(s32) = G_CONSTANT i32 31 + ; CHECK-NEXT: [[ASHR1:%[0-9]+]]:_(s32) = G_ASHR [[COPY5]], [[C3]](s32) + ; CHECK-NEXT: [[C4:%[0-9]+]]:_(s32) = G_CONSTANT i32 0 + ; CHECK-NEXT: [[C5:%[0-9]+]]:_(s32) = G_CONSTANT i32 -2147483648 + ; CHECK-NEXT: [[ADD3:%[0-9]+]]:_(s32) = G_ADD [[ASHR]], [[C4]] + ; CHECK-NEXT: [[ICMP7:%[0-9]+]]:_(s32) = G_ICMP intpred(ult), [[ADD3]](s32), [[C4]] + ; CHECK-NEXT: [[COPY6:%[0-9]+]]:_(s32) = COPY [[ADD3]](s32) + ; CHECK-NEXT: [[ADD4:%[0-9]+]]:_(s32) = G_ADD [[ASHR1]], [[C5]] + ; CHECK-NEXT: [[ADD5:%[0-9]+]]:_(s32) = G_ADD [[ADD4]], [[ICMP7]] + ; CHECK-NEXT: [[COPY7:%[0-9]+]]:_(s32) = COPY [[ADD5]](s32) + ; CHECK-NEXT: [[SELECT2:%[0-9]+]]:_(s32) = G_SELECT [[XOR]](s32), [[COPY6]], [[COPY4]] + ; CHECK-NEXT: [[SELECT3:%[0-9]+]]:_(s32) = G_SELECT [[XOR]](s32), [[COPY7]], [[COPY5]] + ; CHECK-NEXT: $x10 = COPY [[SELECT2]](s32) + ; CHECK-NEXT: $x11 = COPY [[SELECT3]](s32) + ; CHECK-NEXT: PseudoRET implicit $x10, implicit $x11 + %2:_(s32) = COPY $x10 + %3:_(s32) = COPY $x11 + %0:_(s64) = G_MERGE_VALUES %2(s32), %3(s32) + %4:_(s32) = COPY $x12 + %5:_(s32) = COPY $x13 + %1:_(s64) = G_MERGE_VALUES %4(s32), %5(s32) + %6:_(s64) = G_SADDSAT %0, %1(s64) + %7:_(s32), %8:_(s32) = G_UNMERGE_VALUES %6(s64) + $x10 = COPY %7(s32) + $x11 = COPY %8(s32) + PseudoRET implicit $x10, implicit $x11 + +... +--- +name: usubsat_i32 +body: | + bb.1: + liveins: $x10, $x11 + + ; RV32I-LABEL: name: usubsat_i32 + ; RV32I: liveins: $x10, $x11 + ; RV32I-NEXT: {{ $}} + ; RV32I-NEXT: [[COPY:%[0-9]+]]:_(s32) = COPY $x10 + ; RV32I-NEXT: [[COPY1:%[0-9]+]]:_(s32) = COPY $x11 + ; RV32I-NEXT: [[SUB:%[0-9]+]]:_(s32) = G_SUB [[COPY]], [[COPY1]] + ; RV32I-NEXT: [[ICMP:%[0-9]+]]:_(s32) = G_ICMP intpred(ult), [[COPY]](s32), [[COPY1]] + ; RV32I-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 0 + ; RV32I-NEXT: [[SELECT:%[0-9]+]]:_(s32) = G_SELECT [[ICMP]](s32), [[C]], [[SUB]] + ; RV32I-NEXT: $x10 = COPY [[SELECT]](s32) + ; RV32I-NEXT: PseudoRET implicit $x10 + ; + ; RV32ZBB-LABEL: name: usubsat_i32 + ; RV32ZBB: liveins: $x10, $x11 + ; RV32ZBB-NEXT: {{ $}} + ; RV32ZBB-NEXT: [[COPY:%[0-9]+]]:_(s32) = COPY $x10 + ; RV32ZBB-NEXT: [[COPY1:%[0-9]+]]:_(s32) = COPY $x11 + ; RV32ZBB-NEXT: [[UMIN:%[0-9]+]]:_(s32) = G_UMIN [[COPY]], [[COPY1]] + ; RV32ZBB-NEXT: [[SUB:%[0-9]+]]:_(s32) = G_SUB [[COPY]], [[UMIN]] + ; RV32ZBB-NEXT: $x10 = COPY [[SUB]](s32) + ; RV32ZBB-NEXT: PseudoRET implicit $x10 + %0:_(s32) = COPY $x10 + %1:_(s32) = COPY $x11 + %2:_(s32) = G_USUBSAT %0, %1(s32) + $x10 = COPY %2(s32) + PseudoRET implicit $x10 + +... +--- +name: usubsat_i64 +body: | + bb.1: + liveins: $x10, $x11 + ; CHECK-LABEL: name: usubsat_i64 + ; CHECK: liveins: $x10, $x11 + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: [[COPY:%[0-9]+]]:_(s32) = COPY $x10 + ; CHECK-NEXT: [[COPY1:%[0-9]+]]:_(s32) = COPY $x11 + ; CHECK-NEXT: [[COPY2:%[0-9]+]]:_(s32) = COPY $x12 + ; CHECK-NEXT: [[COPY3:%[0-9]+]]:_(s32) = COPY $x13 + ; CHECK-NEXT: [[SUB:%[0-9]+]]:_(s32) = G_SUB [[COPY]], [[COPY2]] + ; CHECK-NEXT: [[ICMP:%[0-9]+]]:_(s32) = G_ICMP intpred(ult), [[COPY]](s32), [[COPY2]] + ; CHECK-NEXT: [[SUB1:%[0-9]+]]:_(s32) = G_SUB [[COPY1]], [[COPY3]] + ; CHECK-NEXT: [[SUB2:%[0-9]+]]:_(s32) = G_SUB [[SUB1]], [[ICMP]] + ; CHECK-NEXT: [[ICMP1:%[0-9]+]]:_(s32) = G_ICMP intpred(ult), [[COPY1]](s32), [[COPY3]] + ; CHECK-NEXT: [[ICMP2:%[0-9]+]]:_(s32) = G_ICMP intpred(eq), [[COPY1]](s32), [[COPY3]] + ; CHECK-NEXT: [[ICMP3:%[0-9]+]]:_(s32) = G_ICMP intpred(ult), [[COPY]](s32), [[COPY2]] + ; CHECK-NEXT: [[SELECT:%[0-9]+]]:_(s32) = G_SELECT [[ICMP2]](s32), [[ICMP3]], [[ICMP1]] + ; CHECK-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 0 + ; CHECK-NEXT: [[C1:%[0-9]+]]:_(s32) = G_CONSTANT i32 0 + ; CHECK-NEXT: [[SELECT1:%[0-9]+]]:_(s32) = G_SELECT [[SELECT]](s32), [[C]], [[SUB]] + ; CHECK-NEXT: [[SELECT2:%[0-9]+]]:_(s32) = G_SELECT [[SELECT]](s32), [[C1]], [[SUB2]] + ; CHECK-NEXT: $x10 = COPY [[SELECT1]](s32) + ; CHECK-NEXT: $x11 = COPY [[SELECT2]](s32) + ; CHECK-NEXT: PseudoRET implicit $x10, implicit $x11 + %2:_(s32) = COPY $x10 + %3:_(s32) = COPY $x11 + %0:_(s64) = G_MERGE_VALUES %2(s32), %3(s32) + %4:_(s32) = COPY $x12 + %5:_(s32) = COPY $x13 + %1:_(s64) = G_MERGE_VALUES %4(s32), %5(s32) + %6:_(s64) = G_USUBSAT %0, %1(s64) + %7:_(s32), %8:_(s32) = G_UNMERGE_VALUES %6(s64) + $x10 = COPY %7(s32) + $x11 = COPY %8(s32) + PseudoRET implicit $x10, implicit $x11 + +... +--- +name: ssubsat_i32 +body: | + bb.1: + liveins: $x10, $x11 + + ; RV32I-LABEL: name: ssubsat_i32 + ; RV32I: liveins: $x10, $x11 + ; RV32I-NEXT: {{ $}} + ; RV32I-NEXT: [[COPY:%[0-9]+]]:_(s32) = COPY $x10 + ; RV32I-NEXT: [[COPY1:%[0-9]+]]:_(s32) = COPY $x11 + ; RV32I-NEXT: [[SUB:%[0-9]+]]:_(s32) = G_SUB [[COPY]], [[COPY1]] + ; RV32I-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 0 + ; RV32I-NEXT: [[ICMP:%[0-9]+]]:_(s32) = G_ICMP intpred(slt), [[SUB]](s32), [[COPY]] + ; RV32I-NEXT: [[ICMP1:%[0-9]+]]:_(s32) = G_ICMP intpred(sgt), [[COPY1]](s32), [[C]] + ; RV32I-NEXT: [[XOR:%[0-9]+]]:_(s32) = G_XOR [[ICMP1]], [[ICMP]] + ; RV32I-NEXT: [[COPY2:%[0-9]+]]:_(s32) = COPY [[SUB]](s32) + ; RV32I-NEXT: [[C1:%[0-9]+]]:_(s32) = G_CONSTANT i32 31 + ; RV32I-NEXT: [[ASHR:%[0-9]+]]:_(s32) = G_ASHR [[COPY2]], [[C1]](s32) + ; RV32I-NEXT: [[C2:%[0-9]+]]:_(s32) = G_CONSTANT i32 -2147483648 + ; RV32I-NEXT: [[ADD:%[0-9]+]]:_(s32) = G_ADD [[ASHR]], [[C2]] + ; RV32I-NEXT: [[SELECT:%[0-9]+]]:_(s32) = G_SELECT [[XOR]](s32), [[ADD]], [[COPY2]] + ; RV32I-NEXT: $x10 = COPY [[SELECT]](s32) + ; RV32I-NEXT: PseudoRET implicit $x10 + ; + ; RV32ZBB-LABEL: name: ssubsat_i32 + ; RV32ZBB: liveins: $x10, $x11 + ; RV32ZBB-NEXT: {{ $}} + ; RV32ZBB-NEXT: [[COPY:%[0-9]+]]:_(s32) = COPY $x10 + ; RV32ZBB-NEXT: [[COPY1:%[0-9]+]]:_(s32) = COPY $x11 + ; RV32ZBB-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 2147483647 + ; RV32ZBB-NEXT: [[C1:%[0-9]+]]:_(s32) = G_CONSTANT i32 -2147483648 + ; RV32ZBB-NEXT: [[C2:%[0-9]+]]:_(s32) = G_CONSTANT i32 -1 + ; RV32ZBB-NEXT: [[SMAX:%[0-9]+]]:_(s32) = G_SMAX [[COPY]], [[C2]] + ; RV32ZBB-NEXT: [[SUB:%[0-9]+]]:_(s32) = G_SUB [[SMAX]], [[C]] + ; RV32ZBB-NEXT: [[SMIN:%[0-9]+]]:_(s32) = G_SMIN [[COPY]], [[C2]] + ; RV32ZBB-NEXT: [[SUB1:%[0-9]+]]:_(s32) = G_SUB [[SMIN]], [[C1]] + ; RV32ZBB-NEXT: [[SMAX1:%[0-9]+]]:_(s32) = G_SMAX [[SUB]], [[COPY1]] + ; RV32ZBB-NEXT: [[SMIN1:%[0-9]+]]:_(s32) = G_SMIN [[SMAX1]], [[SUB1]] + ; RV32ZBB-NEXT: [[SUB2:%[0-9]+]]:_(s32) = G_SUB [[COPY]], [[SMIN1]] + ; RV32ZBB-NEXT: $x10 = COPY [[SUB2]](s32) + ; RV32ZBB-NEXT: PseudoRET implicit $x10 + %0:_(s32) = COPY $x10 + %1:_(s32) = COPY $x11 + %2:_(s32) = G_SSUBSAT %0, %1(s32) + $x10 = COPY %2(s32) + PseudoRET implicit $x10 + +... +--- +name: ssubsat_i64 +body: | + bb.1: + liveins: $x10, $x11 + ; CHECK-LABEL: name: ssubsat_i64 + ; CHECK: liveins: $x10, $x11 + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: [[COPY:%[0-9]+]]:_(s32) = COPY $x10 + ; CHECK-NEXT: [[COPY1:%[0-9]+]]:_(s32) = COPY $x11 + ; CHECK-NEXT: [[COPY2:%[0-9]+]]:_(s32) = COPY $x12 + ; CHECK-NEXT: [[COPY3:%[0-9]+]]:_(s32) = COPY $x13 + ; CHECK-NEXT: [[SUB:%[0-9]+]]:_(s32) = G_SUB [[COPY]], [[COPY2]] + ; CHECK-NEXT: [[ICMP:%[0-9]+]]:_(s32) = G_ICMP intpred(ult), [[COPY]](s32), [[COPY2]] + ; CHECK-NEXT: [[SUB1:%[0-9]+]]:_(s32) = G_SUB [[COPY1]], [[COPY3]] + ; CHECK-NEXT: [[SUB2:%[0-9]+]]:_(s32) = G_SUB [[SUB1]], [[ICMP]] + ; CHECK-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 0 + ; CHECK-NEXT: [[C1:%[0-9]+]]:_(s32) = G_CONSTANT i32 0 + ; CHECK-NEXT: [[ICMP1:%[0-9]+]]:_(s32) = G_ICMP intpred(slt), [[SUB2]](s32), [[COPY1]] + ; CHECK-NEXT: [[ICMP2:%[0-9]+]]:_(s32) = G_ICMP intpred(eq), [[SUB2]](s32), [[COPY1]] + ; CHECK-NEXT: [[ICMP3:%[0-9]+]]:_(s32) = G_ICMP intpred(ult), [[SUB]](s32), [[COPY]] + ; CHECK-NEXT: [[SELECT:%[0-9]+]]:_(s32) = G_SELECT [[ICMP2]](s32), [[ICMP3]], [[ICMP1]] + ; CHECK-NEXT: [[ICMP4:%[0-9]+]]:_(s32) = G_ICMP intpred(sgt), [[COPY3]](s32), [[C1]] + ; CHECK-NEXT: [[ICMP5:%[0-9]+]]:_(s32) = G_ICMP intpred(eq), [[COPY3]](s32), [[C1]] + ; CHECK-NEXT: [[ICMP6:%[0-9]+]]:_(s32) = G_ICMP intpred(ugt), [[COPY2]](s32), [[C]] + ; CHECK-NEXT: [[SELECT1:%[0-9]+]]:_(s32) = G_SELECT [[ICMP5]](s32), [[ICMP6]], [[ICMP4]] + ; CHECK-NEXT: [[XOR:%[0-9]+]]:_(s32) = G_XOR [[SELECT1]], [[SELECT]] + ; CHECK-NEXT: [[C2:%[0-9]+]]:_(s32) = G_CONSTANT i32 31 + ; CHECK-NEXT: [[ASHR:%[0-9]+]]:_(s32) = G_ASHR [[SUB2]], [[C2]](s32) + ; CHECK-NEXT: [[C3:%[0-9]+]]:_(s32) = G_CONSTANT i32 31 + ; CHECK-NEXT: [[ASHR1:%[0-9]+]]:_(s32) = G_ASHR [[SUB2]], [[C3]](s32) + ; CHECK-NEXT: [[C4:%[0-9]+]]:_(s32) = G_CONSTANT i32 0 + ; CHECK-NEXT: [[C5:%[0-9]+]]:_(s32) = G_CONSTANT i32 -2147483648 + ; CHECK-NEXT: [[ADD:%[0-9]+]]:_(s32) = G_ADD [[ASHR]], [[C4]] + ; CHECK-NEXT: [[ICMP7:%[0-9]+]]:_(s32) = G_ICMP intpred(ult), [[ADD]](s32), [[C4]] + ; CHECK-NEXT: [[COPY4:%[0-9]+]]:_(s32) = COPY [[ADD]](s32) + ; CHECK-NEXT: [[ADD1:%[0-9]+]]:_(s32) = G_ADD [[ASHR1]], [[C5]] + ; CHECK-NEXT: [[ADD2:%[0-9]+]]:_(s32) = G_ADD [[ADD1]], [[ICMP7]] + ; CHECK-NEXT: [[COPY5:%[0-9]+]]:_(s32) = COPY [[ADD2]](s32) + ; CHECK-NEXT: [[SELECT2:%[0-9]+]]:_(s32) = G_SELECT [[XOR]](s32), [[COPY4]], [[SUB]] + ; CHECK-NEXT: [[SELECT3:%[0-9]+]]:_(s32) = G_SELECT [[XOR]](s32), [[COPY5]], [[SUB2]] + ; CHECK-NEXT: $x10 = COPY [[SELECT2]](s32) + ; CHECK-NEXT: $x11 = COPY [[SELECT3]](s32) + ; CHECK-NEXT: PseudoRET implicit $x10, implicit $x11 + %2:_(s32) = COPY $x10 + %3:_(s32) = COPY $x11 + %0:_(s64) = G_MERGE_VALUES %2(s32), %3(s32) + %4:_(s32) = COPY $x12 + %5:_(s32) = COPY $x13 + %1:_(s64) = G_MERGE_VALUES %4(s32), %5(s32) + %6:_(s64) = G_SSUBSAT %0, %1(s64) + %7:_(s32), %8:_(s32) = G_UNMERGE_VALUES %6(s64) + $x10 = COPY %7(s32) + $x11 = COPY %8(s32) + PseudoRET implicit $x10, implicit $x11 + +... +--- +name: uaddsat_i8 +body: | + bb.1: + liveins: $x10, $x11 + + ; CHECK-LABEL: name: uaddsat_i8 + ; CHECK: liveins: $x10, $x11 + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: [[COPY:%[0-9]+]]:_(s32) = COPY $x10 + ; CHECK-NEXT: [[COPY1:%[0-9]+]]:_(s32) = COPY $x11 + ; CHECK-NEXT: [[ADD:%[0-9]+]]:_(s32) = G_ADD [[COPY]], [[COPY1]] + ; CHECK-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 255 + ; CHECK-NEXT: [[AND:%[0-9]+]]:_(s32) = G_AND [[ADD]], [[C]] + ; CHECK-NEXT: [[C1:%[0-9]+]]:_(s32) = G_CONSTANT i32 255 + ; CHECK-NEXT: [[AND1:%[0-9]+]]:_(s32) = G_AND [[COPY1]], [[C1]] + ; CHECK-NEXT: [[ICMP:%[0-9]+]]:_(s32) = G_ICMP intpred(ult), [[AND]](s32), [[AND1]] + ; CHECK-NEXT: [[C2:%[0-9]+]]:_(s32) = G_CONSTANT i32 -1 + ; CHECK-NEXT: [[SELECT:%[0-9]+]]:_(s32) = G_SELECT [[ICMP]](s32), [[C2]], [[ADD]] + ; CHECK-NEXT: $x10 = COPY [[SELECT]](s32) + ; CHECK-NEXT: PseudoRET implicit $x10 + %2:_(s32) = COPY $x10 + %0:_(s8) = G_TRUNC %2(s32) + %3:_(s32) = COPY $x11 + %1:_(s8) = G_TRUNC %3(s32) + %4:_(s8) = G_UADDSAT %0, %1(s8) + %5:_(s32) = G_ANYEXT %4(s8) + $x10 = COPY %5(s32) + PseudoRET implicit $x10 + +... diff --git a/llvm/test/CodeGen/RISCV/GlobalISel/legalizer/legalize-sat-rv64.mir b/llvm/test/CodeGen/RISCV/GlobalISel/legalizer/legalize-sat-rv64.mir new file mode 100644 index 000000000000..5eaf8b37fe98 --- /dev/null +++ b/llvm/test/CodeGen/RISCV/GlobalISel/legalizer/legalize-sat-rv64.mir @@ -0,0 +1,358 @@ +# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py UTC_ARGS: --version 5 +# RUN: llc -mtriple=riscv64 -run-pass=legalizer %s -o - \ +# RUN: | FileCheck %s --check-prefixes=CHECK,RV64I +# RUN: llc -mtriple=riscv64 -mattr=+zbb -run-pass=legalizer %s -o - \ +# RUN: | FileCheck %s --check-prefixes=CHECK,RV64ZBB + +--- +name: uaddsat_i32 +body: | + bb.1: + liveins: $x10, $x11 + + ; CHECK-LABEL: name: uaddsat_i32 + ; CHECK: liveins: $x10, $x11 + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: [[COPY:%[0-9]+]]:_(s64) = COPY $x10 + ; CHECK-NEXT: [[TRUNC:%[0-9]+]]:_(s32) = G_TRUNC [[COPY]](s64) + ; CHECK-NEXT: [[COPY1:%[0-9]+]]:_(s64) = COPY $x11 + ; CHECK-NEXT: [[TRUNC1:%[0-9]+]]:_(s32) = G_TRUNC [[COPY1]](s64) + ; CHECK-NEXT: [[ADD:%[0-9]+]]:_(s32) = G_ADD [[TRUNC]], [[TRUNC1]] + ; CHECK-NEXT: [[ZEXT:%[0-9]+]]:_(s64) = G_ZEXT [[ADD]](s32) + ; CHECK-NEXT: [[C:%[0-9]+]]:_(s64) = G_CONSTANT i64 4294967295 + ; CHECK-NEXT: [[AND:%[0-9]+]]:_(s64) = G_AND [[COPY1]], [[C]] + ; CHECK-NEXT: [[ICMP:%[0-9]+]]:_(s64) = G_ICMP intpred(ult), [[ZEXT]](s64), [[AND]] + ; CHECK-NEXT: [[COPY2:%[0-9]+]]:_(s32) = COPY [[ADD]](s32) + ; CHECK-NEXT: [[C1:%[0-9]+]]:_(s32) = G_CONSTANT i32 -1 + ; CHECK-NEXT: [[SELECT:%[0-9]+]]:_(s32) = G_SELECT [[ICMP]](s64), [[C1]], [[COPY2]] + ; CHECK-NEXT: [[ANYEXT:%[0-9]+]]:_(s64) = G_ANYEXT [[SELECT]](s32) + ; CHECK-NEXT: $x10 = COPY [[ANYEXT]](s64) + ; CHECK-NEXT: PseudoRET implicit $x10 + %2:_(s64) = COPY $x10 + %0:_(s32) = G_TRUNC %2(s64) + %3:_(s64) = COPY $x11 + %1:_(s32) = G_TRUNC %3(s64) + %4:_(s32) = G_UADDSAT %0, %1(s32) + %5:_(s64) = G_ANYEXT %4(s32) + $x10 = COPY %5(s64) + PseudoRET implicit $x10 + +... +--- +name: uaddsat_i64 +body: | + bb.1: + liveins: $x10, $x11 + + ; RV64I-LABEL: name: uaddsat_i64 + ; RV64I: liveins: $x10, $x11 + ; RV64I-NEXT: {{ $}} + ; RV64I-NEXT: [[COPY:%[0-9]+]]:_(s64) = COPY $x10 + ; RV64I-NEXT: [[COPY1:%[0-9]+]]:_(s64) = COPY $x11 + ; RV64I-NEXT: [[ADD:%[0-9]+]]:_(s64) = G_ADD [[COPY]], [[COPY1]] + ; RV64I-NEXT: [[ICMP:%[0-9]+]]:_(s64) = G_ICMP intpred(ult), [[ADD]](s64), [[COPY1]] + ; RV64I-NEXT: [[COPY2:%[0-9]+]]:_(s64) = COPY [[ADD]](s64) + ; RV64I-NEXT: [[C:%[0-9]+]]:_(s64) = G_CONSTANT i64 -1 + ; RV64I-NEXT: [[SELECT:%[0-9]+]]:_(s64) = G_SELECT [[ICMP]](s64), [[C]], [[COPY2]] + ; RV64I-NEXT: $x10 = COPY [[SELECT]](s64) + ; RV64I-NEXT: PseudoRET implicit $x10 + ; + ; RV64ZBB-LABEL: name: uaddsat_i64 + ; RV64ZBB: liveins: $x10, $x11 + ; RV64ZBB-NEXT: {{ $}} + ; RV64ZBB-NEXT: [[COPY:%[0-9]+]]:_(s64) = COPY $x10 + ; RV64ZBB-NEXT: [[COPY1:%[0-9]+]]:_(s64) = COPY $x11 + ; RV64ZBB-NEXT: [[C:%[0-9]+]]:_(s64) = G_CONSTANT i64 -1 + ; RV64ZBB-NEXT: [[XOR:%[0-9]+]]:_(s64) = G_XOR [[COPY]], [[C]] + ; RV64ZBB-NEXT: [[UMIN:%[0-9]+]]:_(s64) = G_UMIN [[XOR]], [[COPY1]] + ; RV64ZBB-NEXT: [[ADD:%[0-9]+]]:_(s64) = G_ADD [[COPY]], [[UMIN]] + ; RV64ZBB-NEXT: $x10 = COPY [[ADD]](s64) + ; RV64ZBB-NEXT: PseudoRET implicit $x10 + %0:_(s64) = COPY $x10 + %1:_(s64) = COPY $x11 + %2:_(s64) = G_UADDSAT %0, %1(s64) + $x10 = COPY %2(s64) + PseudoRET implicit $x10 + +... +--- +name: saddsat_i32 +body: | + bb.1: + liveins: $x10, $x11 + + ; CHECK-LABEL: name: saddsat_i32 + ; CHECK: liveins: $x10, $x11 + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: [[COPY:%[0-9]+]]:_(s64) = COPY $x10 + ; CHECK-NEXT: [[COPY1:%[0-9]+]]:_(s64) = COPY $x11 + ; CHECK-NEXT: [[SEXT_INREG:%[0-9]+]]:_(s64) = G_SEXT_INREG [[COPY]], 32 + ; CHECK-NEXT: [[SEXT_INREG1:%[0-9]+]]:_(s64) = G_SEXT_INREG [[COPY1]], 32 + ; CHECK-NEXT: [[ADD:%[0-9]+]]:_(s64) = G_ADD [[SEXT_INREG]], [[SEXT_INREG1]] + ; CHECK-NEXT: [[SEXT_INREG2:%[0-9]+]]:_(s64) = G_SEXT_INREG [[ADD]], 32 + ; CHECK-NEXT: [[ICMP:%[0-9]+]]:_(s64) = G_ICMP intpred(ne), [[ADD]](s64), [[SEXT_INREG2]] + ; CHECK-NEXT: [[TRUNC:%[0-9]+]]:_(s32) = G_TRUNC [[ADD]](s64) + ; CHECK-NEXT: [[C:%[0-9]+]]:_(s64) = G_CONSTANT i64 31 + ; CHECK-NEXT: [[ASHR:%[0-9]+]]:_(s32) = G_ASHR [[TRUNC]], [[C]](s64) + ; CHECK-NEXT: [[C1:%[0-9]+]]:_(s32) = G_CONSTANT i32 -2147483648 + ; CHECK-NEXT: [[ADD1:%[0-9]+]]:_(s32) = G_ADD [[ASHR]], [[C1]] + ; CHECK-NEXT: [[SELECT:%[0-9]+]]:_(s32) = G_SELECT [[ICMP]](s64), [[ADD1]], [[TRUNC]] + ; CHECK-NEXT: [[ANYEXT:%[0-9]+]]:_(s64) = G_ANYEXT [[SELECT]](s32) + ; CHECK-NEXT: $x10 = COPY [[ANYEXT]](s64) + ; CHECK-NEXT: PseudoRET implicit $x10 + %2:_(s64) = COPY $x10 + %0:_(s32) = G_TRUNC %2(s64) + %3:_(s64) = COPY $x11 + %1:_(s32) = G_TRUNC %3(s64) + %4:_(s32) = G_SADDSAT %0, %1(s32) + %5:_(s64) = G_ANYEXT %4(s32) + $x10 = COPY %5(s64) + PseudoRET implicit $x10 + +... +--- +name: saddsat_i64 +body: | + bb.1: + liveins: $x10, $x11 + + ; RV64I-LABEL: name: saddsat_i64 + ; RV64I: liveins: $x10, $x11 + ; RV64I-NEXT: {{ $}} + ; RV64I-NEXT: [[COPY:%[0-9]+]]:_(s64) = COPY $x10 + ; RV64I-NEXT: [[COPY1:%[0-9]+]]:_(s64) = COPY $x11 + ; RV64I-NEXT: [[ADD:%[0-9]+]]:_(s64) = G_ADD [[COPY]], [[COPY1]] + ; RV64I-NEXT: [[C:%[0-9]+]]:_(s64) = G_CONSTANT i64 0 + ; RV64I-NEXT: [[ICMP:%[0-9]+]]:_(s64) = G_ICMP intpred(slt), [[ADD]](s64), [[COPY]] + ; RV64I-NEXT: [[ICMP1:%[0-9]+]]:_(s64) = G_ICMP intpred(slt), [[COPY1]](s64), [[C]] + ; RV64I-NEXT: [[TRUNC:%[0-9]+]]:_(s32) = G_TRUNC [[ICMP1]](s64) + ; RV64I-NEXT: [[TRUNC1:%[0-9]+]]:_(s32) = G_TRUNC [[ICMP]](s64) + ; RV64I-NEXT: [[XOR:%[0-9]+]]:_(s32) = G_XOR [[TRUNC]], [[TRUNC1]] + ; RV64I-NEXT: [[COPY2:%[0-9]+]]:_(s64) = COPY [[ADD]](s64) + ; RV64I-NEXT: [[C1:%[0-9]+]]:_(s64) = G_CONSTANT i64 63 + ; RV64I-NEXT: [[ASHR:%[0-9]+]]:_(s64) = G_ASHR [[COPY2]], [[C1]](s64) + ; RV64I-NEXT: [[C2:%[0-9]+]]:_(s64) = G_CONSTANT i64 -9223372036854775808 + ; RV64I-NEXT: [[ADD1:%[0-9]+]]:_(s64) = G_ADD [[ASHR]], [[C2]] + ; RV64I-NEXT: [[ANYEXT:%[0-9]+]]:_(s64) = G_ANYEXT [[XOR]](s32) + ; RV64I-NEXT: [[C3:%[0-9]+]]:_(s64) = G_CONSTANT i64 1 + ; RV64I-NEXT: [[AND:%[0-9]+]]:_(s64) = G_AND [[ANYEXT]], [[C3]] + ; RV64I-NEXT: [[SELECT:%[0-9]+]]:_(s64) = G_SELECT [[AND]](s64), [[ADD1]], [[COPY2]] + ; RV64I-NEXT: $x10 = COPY [[SELECT]](s64) + ; RV64I-NEXT: PseudoRET implicit $x10 + ; + ; RV64ZBB-LABEL: name: saddsat_i64 + ; RV64ZBB: liveins: $x10, $x11 + ; RV64ZBB-NEXT: {{ $}} + ; RV64ZBB-NEXT: [[COPY:%[0-9]+]]:_(s64) = COPY $x10 + ; RV64ZBB-NEXT: [[COPY1:%[0-9]+]]:_(s64) = COPY $x11 + ; RV64ZBB-NEXT: [[C:%[0-9]+]]:_(s64) = G_CONSTANT i64 9223372036854775807 + ; RV64ZBB-NEXT: [[C1:%[0-9]+]]:_(s64) = G_CONSTANT i64 -9223372036854775808 + ; RV64ZBB-NEXT: [[C2:%[0-9]+]]:_(s64) = G_CONSTANT i64 0 + ; RV64ZBB-NEXT: [[SMAX:%[0-9]+]]:_(s64) = G_SMAX [[COPY]], [[C2]] + ; RV64ZBB-NEXT: [[SUB:%[0-9]+]]:_(s64) = G_SUB [[C]], [[SMAX]] + ; RV64ZBB-NEXT: [[SMIN:%[0-9]+]]:_(s64) = G_SMIN [[COPY]], [[C2]] + ; RV64ZBB-NEXT: [[SUB1:%[0-9]+]]:_(s64) = G_SUB [[C1]], [[SMIN]] + ; RV64ZBB-NEXT: [[SMAX1:%[0-9]+]]:_(s64) = G_SMAX [[SUB1]], [[COPY1]] + ; RV64ZBB-NEXT: [[SMIN1:%[0-9]+]]:_(s64) = G_SMIN [[SMAX1]], [[SUB]] + ; RV64ZBB-NEXT: [[ADD:%[0-9]+]]:_(s64) = G_ADD [[COPY]], [[SMIN1]] + ; RV64ZBB-NEXT: $x10 = COPY [[ADD]](s64) + ; RV64ZBB-NEXT: PseudoRET implicit $x10 + %0:_(s64) = COPY $x10 + %1:_(s64) = COPY $x11 + %2:_(s64) = G_SADDSAT %0, %1(s64) + $x10 = COPY %2(s64) + PseudoRET implicit $x10 + +... +--- +name: usubsat_i32 +body: | + bb.1: + liveins: $x10, $x11 + + ; CHECK-LABEL: name: usubsat_i32 + ; CHECK: liveins: $x10, $x11 + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: [[COPY:%[0-9]+]]:_(s64) = COPY $x10 + ; CHECK-NEXT: [[TRUNC:%[0-9]+]]:_(s32) = G_TRUNC [[COPY]](s64) + ; CHECK-NEXT: [[COPY1:%[0-9]+]]:_(s64) = COPY $x11 + ; CHECK-NEXT: [[TRUNC1:%[0-9]+]]:_(s32) = G_TRUNC [[COPY1]](s64) + ; CHECK-NEXT: [[SUB:%[0-9]+]]:_(s32) = G_SUB [[TRUNC]], [[TRUNC1]] + ; CHECK-NEXT: [[C:%[0-9]+]]:_(s64) = G_CONSTANT i64 4294967295 + ; CHECK-NEXT: [[AND:%[0-9]+]]:_(s64) = G_AND [[COPY]], [[C]] + ; CHECK-NEXT: [[C1:%[0-9]+]]:_(s64) = G_CONSTANT i64 4294967295 + ; CHECK-NEXT: [[AND1:%[0-9]+]]:_(s64) = G_AND [[COPY1]], [[C1]] + ; CHECK-NEXT: [[ICMP:%[0-9]+]]:_(s64) = G_ICMP intpred(ult), [[AND]](s64), [[AND1]] + ; CHECK-NEXT: [[C2:%[0-9]+]]:_(s32) = G_CONSTANT i32 0 + ; CHECK-NEXT: [[SELECT:%[0-9]+]]:_(s32) = G_SELECT [[ICMP]](s64), [[C2]], [[SUB]] + ; CHECK-NEXT: [[ANYEXT:%[0-9]+]]:_(s64) = G_ANYEXT [[SELECT]](s32) + ; CHECK-NEXT: $x10 = COPY [[ANYEXT]](s64) + ; CHECK-NEXT: PseudoRET implicit $x10 + %2:_(s64) = COPY $x10 + %0:_(s32) = G_TRUNC %2(s64) + %3:_(s64) = COPY $x11 + %1:_(s32) = G_TRUNC %3(s64) + %4:_(s32) = G_USUBSAT %0, %1(s32) + %5:_(s64) = G_ANYEXT %4(s32) + $x10 = COPY %5(s64) + PseudoRET implicit $x10 + +... +--- +name: usubsat_i64 +body: | + bb.1: + liveins: $x10, $x11 + + ; RV64I-LABEL: name: usubsat_i64 + ; RV64I: liveins: $x10, $x11 + ; RV64I-NEXT: {{ $}} + ; RV64I-NEXT: [[COPY:%[0-9]+]]:_(s64) = COPY $x10 + ; RV64I-NEXT: [[COPY1:%[0-9]+]]:_(s64) = COPY $x11 + ; RV64I-NEXT: [[SUB:%[0-9]+]]:_(s64) = G_SUB [[COPY]], [[COPY1]] + ; RV64I-NEXT: [[ICMP:%[0-9]+]]:_(s64) = G_ICMP intpred(ult), [[COPY]](s64), [[COPY1]] + ; RV64I-NEXT: [[C:%[0-9]+]]:_(s64) = G_CONSTANT i64 0 + ; RV64I-NEXT: [[SELECT:%[0-9]+]]:_(s64) = G_SELECT [[ICMP]](s64), [[C]], [[SUB]] + ; RV64I-NEXT: $x10 = COPY [[SELECT]](s64) + ; RV64I-NEXT: PseudoRET implicit $x10 + ; + ; RV64ZBB-LABEL: name: usubsat_i64 + ; RV64ZBB: liveins: $x10, $x11 + ; RV64ZBB-NEXT: {{ $}} + ; RV64ZBB-NEXT: [[COPY:%[0-9]+]]:_(s64) = COPY $x10 + ; RV64ZBB-NEXT: [[COPY1:%[0-9]+]]:_(s64) = COPY $x11 + ; RV64ZBB-NEXT: [[UMIN:%[0-9]+]]:_(s64) = G_UMIN [[COPY]], [[COPY1]] + ; RV64ZBB-NEXT: [[SUB:%[0-9]+]]:_(s64) = G_SUB [[COPY]], [[UMIN]] + ; RV64ZBB-NEXT: $x10 = COPY [[SUB]](s64) + ; RV64ZBB-NEXT: PseudoRET implicit $x10 + %0:_(s64) = COPY $x10 + %1:_(s64) = COPY $x11 + %2:_(s64) = G_USUBSAT %0, %1(s64) + $x10 = COPY %2(s64) + PseudoRET implicit $x10 + +... +--- +name: ssubsat_i32 +body: | + bb.1: + liveins: $x10, $x11 + + ; CHECK-LABEL: name: ssubsat_i32 + ; CHECK: liveins: $x10, $x11 + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: [[COPY:%[0-9]+]]:_(s64) = COPY $x10 + ; CHECK-NEXT: [[COPY1:%[0-9]+]]:_(s64) = COPY $x11 + ; CHECK-NEXT: [[SEXT_INREG:%[0-9]+]]:_(s64) = G_SEXT_INREG [[COPY]], 32 + ; CHECK-NEXT: [[SEXT_INREG1:%[0-9]+]]:_(s64) = G_SEXT_INREG [[COPY1]], 32 + ; CHECK-NEXT: [[SUB:%[0-9]+]]:_(s64) = G_SUB [[SEXT_INREG]], [[SEXT_INREG1]] + ; CHECK-NEXT: [[SEXT_INREG2:%[0-9]+]]:_(s64) = G_SEXT_INREG [[SUB]], 32 + ; CHECK-NEXT: [[ICMP:%[0-9]+]]:_(s64) = G_ICMP intpred(ne), [[SUB]](s64), [[SEXT_INREG2]] + ; CHECK-NEXT: [[TRUNC:%[0-9]+]]:_(s32) = G_TRUNC [[SUB]](s64) + ; CHECK-NEXT: [[C:%[0-9]+]]:_(s64) = G_CONSTANT i64 31 + ; CHECK-NEXT: [[ASHR:%[0-9]+]]:_(s32) = G_ASHR [[TRUNC]], [[C]](s64) + ; CHECK-NEXT: [[C1:%[0-9]+]]:_(s32) = G_CONSTANT i32 -2147483648 + ; CHECK-NEXT: [[ADD:%[0-9]+]]:_(s32) = G_ADD [[ASHR]], [[C1]] + ; CHECK-NEXT: [[SELECT:%[0-9]+]]:_(s32) = G_SELECT [[ICMP]](s64), [[ADD]], [[TRUNC]] + ; CHECK-NEXT: [[ANYEXT:%[0-9]+]]:_(s64) = G_ANYEXT [[SELECT]](s32) + ; CHECK-NEXT: $x10 = COPY [[ANYEXT]](s64) + ; CHECK-NEXT: PseudoRET implicit $x10 + %2:_(s64) = COPY $x10 + %0:_(s32) = G_TRUNC %2(s64) + %3:_(s64) = COPY $x11 + %1:_(s32) = G_TRUNC %3(s64) + %4:_(s32) = G_SSUBSAT %0, %1(s32) + %5:_(s64) = G_ANYEXT %4(s32) + $x10 = COPY %5(s64) + PseudoRET implicit $x10 + +... +--- +name: ssubsat_i64 +body: | + bb.1: + liveins: $x10, $x11 + + ; RV64I-LABEL: name: ssubsat_i64 + ; RV64I: liveins: $x10, $x11 + ; RV64I-NEXT: {{ $}} + ; RV64I-NEXT: [[COPY:%[0-9]+]]:_(s64) = COPY $x10 + ; RV64I-NEXT: [[COPY1:%[0-9]+]]:_(s64) = COPY $x11 + ; RV64I-NEXT: [[SUB:%[0-9]+]]:_(s64) = G_SUB [[COPY]], [[COPY1]] + ; RV64I-NEXT: [[C:%[0-9]+]]:_(s64) = G_CONSTANT i64 0 + ; RV64I-NEXT: [[ICMP:%[0-9]+]]:_(s64) = G_ICMP intpred(slt), [[SUB]](s64), [[COPY]] + ; RV64I-NEXT: [[ICMP1:%[0-9]+]]:_(s64) = G_ICMP intpred(sgt), [[COPY1]](s64), [[C]] + ; RV64I-NEXT: [[TRUNC:%[0-9]+]]:_(s32) = G_TRUNC [[ICMP1]](s64) + ; RV64I-NEXT: [[TRUNC1:%[0-9]+]]:_(s32) = G_TRUNC [[ICMP]](s64) + ; RV64I-NEXT: [[XOR:%[0-9]+]]:_(s32) = G_XOR [[TRUNC]], [[TRUNC1]] + ; RV64I-NEXT: [[COPY2:%[0-9]+]]:_(s64) = COPY [[SUB]](s64) + ; RV64I-NEXT: [[C1:%[0-9]+]]:_(s64) = G_CONSTANT i64 63 + ; RV64I-NEXT: [[ASHR:%[0-9]+]]:_(s64) = G_ASHR [[COPY2]], [[C1]](s64) + ; RV64I-NEXT: [[C2:%[0-9]+]]:_(s64) = G_CONSTANT i64 -9223372036854775808 + ; RV64I-NEXT: [[ADD:%[0-9]+]]:_(s64) = G_ADD [[ASHR]], [[C2]] + ; RV64I-NEXT: [[ANYEXT:%[0-9]+]]:_(s64) = G_ANYEXT [[XOR]](s32) + ; RV64I-NEXT: [[C3:%[0-9]+]]:_(s64) = G_CONSTANT i64 1 + ; RV64I-NEXT: [[AND:%[0-9]+]]:_(s64) = G_AND [[ANYEXT]], [[C3]] + ; RV64I-NEXT: [[SELECT:%[0-9]+]]:_(s64) = G_SELECT [[AND]](s64), [[ADD]], [[COPY2]] + ; RV64I-NEXT: $x10 = COPY [[SELECT]](s64) + ; RV64I-NEXT: PseudoRET implicit $x10 + ; + ; RV64ZBB-LABEL: name: ssubsat_i64 + ; RV64ZBB: liveins: $x10, $x11 + ; RV64ZBB-NEXT: {{ $}} + ; RV64ZBB-NEXT: [[COPY:%[0-9]+]]:_(s64) = COPY $x10 + ; RV64ZBB-NEXT: [[COPY1:%[0-9]+]]:_(s64) = COPY $x11 + ; RV64ZBB-NEXT: [[C:%[0-9]+]]:_(s64) = G_CONSTANT i64 9223372036854775807 + ; RV64ZBB-NEXT: [[C1:%[0-9]+]]:_(s64) = G_CONSTANT i64 -9223372036854775808 + ; RV64ZBB-NEXT: [[C2:%[0-9]+]]:_(s64) = G_CONSTANT i64 -1 + ; RV64ZBB-NEXT: [[SMAX:%[0-9]+]]:_(s64) = G_SMAX [[COPY]], [[C2]] + ; RV64ZBB-NEXT: [[SUB:%[0-9]+]]:_(s64) = G_SUB [[SMAX]], [[C]] + ; RV64ZBB-NEXT: [[SMIN:%[0-9]+]]:_(s64) = G_SMIN [[COPY]], [[C2]] + ; RV64ZBB-NEXT: [[SUB1:%[0-9]+]]:_(s64) = G_SUB [[SMIN]], [[C1]] + ; RV64ZBB-NEXT: [[SMAX1:%[0-9]+]]:_(s64) = G_SMAX [[SUB]], [[COPY1]] + ; RV64ZBB-NEXT: [[SMIN1:%[0-9]+]]:_(s64) = G_SMIN [[SMAX1]], [[SUB1]] + ; RV64ZBB-NEXT: [[SUB2:%[0-9]+]]:_(s64) = G_SUB [[COPY]], [[SMIN1]] + ; RV64ZBB-NEXT: $x10 = COPY [[SUB2]](s64) + ; RV64ZBB-NEXT: PseudoRET implicit $x10 + %0:_(s64) = COPY $x10 + %1:_(s64) = COPY $x11 + %2:_(s64) = G_SSUBSAT %0, %1(s64) + $x10 = COPY %2(s64) + PseudoRET implicit $x10 + +... +--- +name: uaddsat_i8 +body: | + bb.1: + liveins: $x10, $x11 + + ; CHECK-LABEL: name: uaddsat_i8 + ; CHECK: liveins: $x10, $x11 + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: [[COPY:%[0-9]+]]:_(s64) = COPY $x10 + ; CHECK-NEXT: [[COPY1:%[0-9]+]]:_(s64) = COPY $x11 + ; CHECK-NEXT: [[TRUNC:%[0-9]+]]:_(s32) = G_TRUNC [[COPY]](s64) + ; CHECK-NEXT: [[TRUNC1:%[0-9]+]]:_(s32) = G_TRUNC [[COPY1]](s64) + ; CHECK-NEXT: [[ADD:%[0-9]+]]:_(s32) = G_ADD [[TRUNC]], [[TRUNC1]] + ; CHECK-NEXT: [[ANYEXT:%[0-9]+]]:_(s64) = G_ANYEXT [[ADD]](s32) + ; CHECK-NEXT: [[C:%[0-9]+]]:_(s64) = G_CONSTANT i64 255 + ; CHECK-NEXT: [[AND:%[0-9]+]]:_(s64) = G_AND [[ANYEXT]], [[C]] + ; CHECK-NEXT: [[C1:%[0-9]+]]:_(s64) = G_CONSTANT i64 255 + ; CHECK-NEXT: [[AND1:%[0-9]+]]:_(s64) = G_AND [[COPY1]], [[C1]] + ; CHECK-NEXT: [[ICMP:%[0-9]+]]:_(s64) = G_ICMP intpred(ult), [[AND]](s64), [[AND1]] + ; CHECK-NEXT: [[C2:%[0-9]+]]:_(s32) = G_CONSTANT i32 -1 + ; CHECK-NEXT: [[SELECT:%[0-9]+]]:_(s32) = G_SELECT [[ICMP]](s64), [[C2]], [[ADD]] + ; CHECK-NEXT: [[ANYEXT1:%[0-9]+]]:_(s64) = G_ANYEXT [[SELECT]](s32) + ; CHECK-NEXT: $x10 = COPY [[ANYEXT1]](s64) + ; CHECK-NEXT: PseudoRET implicit $x10 + %2:_(s64) = COPY $x10 + %0:_(s8) = G_TRUNC %2(s64) + %3:_(s64) = COPY $x11 + %1:_(s8) = G_TRUNC %3(s64) + %4:_(s8) = G_UADDSAT %0, %1(s8) + %5:_(s64) = G_ANYEXT %4(s8) + $x10 = COPY %5(s64) + PseudoRET implicit $x10 + +... -- GitLab From 89c23f7683efbdf896670218be9095d57ae3e348 Mon Sep 17 00:00:00 2001 From: Sven van Haastregt Date: Wed, 22 May 2024 09:38:01 +0200 Subject: [PATCH 081/452] [SPIR-V] Add cl_khr_kernel_clock / SPV_KHR_shader_clock extension (#92771) Recognize `cl_khr_kernel_clock` builtins and translate them to `OpReadClockKHR` instructions. The `Scope` operand is deduced from the builtin function name. spirv-val does not pass yet due to OpReadClockKHR only supporting the valid scopes for Vulkan (Device and Subgroup, but not Workgroup), so leave validation disabled with a TODO. --- llvm/lib/Target/SPIRV/SPIRVBuiltins.cpp | 35 +++++++++++ llvm/lib/Target/SPIRV/SPIRVBuiltins.td | 9 +++ llvm/lib/Target/SPIRV/SPIRVCommandLine.cpp | 2 + llvm/lib/Target/SPIRV/SPIRVInstrInfo.td | 5 ++ llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp | 8 +++ .../lib/Target/SPIRV/SPIRVSymbolicOperands.td | 1 + .../SPV_KHR_shader_clock/shader_clock.ll | 59 +++++++++++++++++++ 7 files changed, 119 insertions(+) create mode 100644 llvm/test/CodeGen/SPIRV/extensions/SPV_KHR_shader_clock/shader_clock.ll diff --git a/llvm/lib/Target/SPIRV/SPIRVBuiltins.cpp b/llvm/lib/Target/SPIRV/SPIRVBuiltins.cpp index 9fde26c900f5..424087f361a6 100644 --- a/llvm/lib/Target/SPIRV/SPIRVBuiltins.cpp +++ b/llvm/lib/Target/SPIRV/SPIRVBuiltins.cpp @@ -1118,6 +1118,39 @@ static bool generateGroupUniformInst(const SPIRV::IncomingCall *Call, return true; } +static bool generateKernelClockInst(const SPIRV::IncomingCall *Call, + MachineIRBuilder &MIRBuilder, + SPIRVGlobalRegistry *GR) { + const SPIRV::DemangledBuiltin *Builtin = Call->Builtin; + MachineFunction &MF = MIRBuilder.getMF(); + const auto *ST = static_cast(&MF.getSubtarget()); + if (!ST->canUseExtension(SPIRV::Extension::SPV_KHR_shader_clock)) { + std::string DiagMsg = std::string(Builtin->Name) + + ": the builtin requires the following SPIR-V " + "extension: SPV_KHR_shader_clock"; + report_fatal_error(DiagMsg.c_str(), false); + } + + MachineRegisterInfo *MRI = MIRBuilder.getMRI(); + Register ResultReg = Call->ReturnRegister; + MRI->setRegClass(ResultReg, &SPIRV::IDRegClass); + + // Deduce the `Scope` operand from the builtin function name. + SPIRV::Scope::Scope ScopeArg = + StringSwitch(Builtin->Name) + .EndsWith("device", SPIRV::Scope::Scope::Device) + .EndsWith("work_group", SPIRV::Scope::Scope::Workgroup) + .EndsWith("sub_group", SPIRV::Scope::Scope::Subgroup); + Register ScopeReg = buildConstantIntReg(ScopeArg, MIRBuilder, GR); + + MIRBuilder.buildInstr(SPIRV::OpReadClockKHR) + .addDef(ResultReg) + .addUse(GR->getSPIRVTypeID(Call->ReturnType)) + .addUse(ScopeReg); + + return true; +} + // These queries ask for a single size_t result for a given dimension index, e.g // size_t get_global_id(uint dimindex). In SPIR-V, the builtins corresonding to // these values are all vec3 types, so we need to extract the correct index or @@ -2290,6 +2323,8 @@ std::optional lowerBuiltin(const StringRef DemangledCall, return generateIntelSubgroupsInst(Call.get(), MIRBuilder, GR); case SPIRV::GroupUniform: return generateGroupUniformInst(Call.get(), MIRBuilder, GR); + case SPIRV::KernelClock: + return generateKernelClockInst(Call.get(), MIRBuilder, GR); } return false; } diff --git a/llvm/lib/Target/SPIRV/SPIRVBuiltins.td b/llvm/lib/Target/SPIRV/SPIRVBuiltins.td index 564028547821..692234c405ab 100644 --- a/llvm/lib/Target/SPIRV/SPIRVBuiltins.td +++ b/llvm/lib/Target/SPIRV/SPIRVBuiltins.td @@ -58,6 +58,7 @@ def LoadStore : BuiltinGroup; def IntelSubgroups : BuiltinGroup; def AtomicFloating : BuiltinGroup; def GroupUniform : BuiltinGroup; +def KernelClock : BuiltinGroup; //===----------------------------------------------------------------------===// // Class defining a demangled builtin record. The information in the record @@ -952,6 +953,14 @@ defm : DemangledGroupBuiltin<"group_scan_exclusive_logical_xor", OnlyWork, OpGro defm : DemangledGroupBuiltin<"group_scan_inclusive_logical_xor", OnlyWork, OpGroupLogicalXorKHR>; defm : DemangledGroupBuiltin<"group_reduce_logical_xor", OnlyWork, OpGroupLogicalXorKHR>; +// cl_khr_kernel_clock / SPV_KHR_shader_clock +defm : DemangledNativeBuiltin<"clock_read_device", OpenCL_std, KernelClock, 0, 0, OpReadClockKHR>; +defm : DemangledNativeBuiltin<"clock_read_work_group", OpenCL_std, KernelClock, 0, 0, OpReadClockKHR>; +defm : DemangledNativeBuiltin<"clock_read_sub_group", OpenCL_std, KernelClock, 0, 0, OpReadClockKHR>; +defm : DemangledNativeBuiltin<"clock_read_hilo_device", OpenCL_std, KernelClock, 0, 0, OpReadClockKHR>; +defm : DemangledNativeBuiltin<"clock_read_hilo_work_group", OpenCL_std, KernelClock, 0, 0, OpReadClockKHR>; +defm : DemangledNativeBuiltin<"clock_read_hilo_sub_group", OpenCL_std, KernelClock, 0, 0, OpReadClockKHR>; + //===----------------------------------------------------------------------===// // Class defining an atomic instruction on floating-point numbers. // diff --git a/llvm/lib/Target/SPIRV/SPIRVCommandLine.cpp b/llvm/lib/Target/SPIRV/SPIRVCommandLine.cpp index 691e6ee0e582..752d71eddd99 100644 --- a/llvm/lib/Target/SPIRV/SPIRVCommandLine.cpp +++ b/llvm/lib/Target/SPIRV/SPIRVCommandLine.cpp @@ -55,6 +55,8 @@ static const std::map SPIRV::Extension::Extension::SPV_INTEL_variable_length_array}, {"SPV_INTEL_function_pointers", SPIRV::Extension::Extension::SPV_INTEL_function_pointers}, + {"SPV_KHR_shader_clock", + SPIRV::Extension::Extension::SPV_KHR_shader_clock}, }; bool SPIRVExtensionsParser::parse(cl::Option &O, llvm::StringRef ArgName, diff --git a/llvm/lib/Target/SPIRV/SPIRVInstrInfo.td b/llvm/lib/Target/SPIRV/SPIRVInstrInfo.td index 151d0ec1fe56..a6bedab6d4ee 100644 --- a/llvm/lib/Target/SPIRV/SPIRVInstrInfo.td +++ b/llvm/lib/Target/SPIRV/SPIRVInstrInfo.td @@ -802,6 +802,11 @@ def OpGroupNonUniformRotateKHR: Op<4431, (outs ID:$res), (ins TYPE:$type, ID:$scope, ID:$value, ID:$delta, variable_ops), "$res = OpGroupNonUniformRotateKHR $type $scope $value $delta">; +// SPV_KHR_shader_clock +def OpReadClockKHR: Op<5056, (outs ID:$res), + (ins TYPE:$type, ID:$scope), + "$res = OpReadClockKHR $type $scope">; + // 3.49.7, Constant-Creation Instructions // - SPV_INTEL_function_pointers diff --git a/llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp b/llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp index 235f947901d8..cbe7c5ca3057 100644 --- a/llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp +++ b/llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp @@ -1117,6 +1117,14 @@ void addInstrRequirements(const MachineInstr &MI, Reqs.addCapability(SPIRV::Capability::GroupUniformArithmeticKHR); } break; + case SPIRV::OpReadClockKHR: + if (!ST.canUseExtension(SPIRV::Extension::SPV_KHR_shader_clock)) + report_fatal_error("OpReadClockKHR instruction requires the " + "following SPIR-V extension: SPV_KHR_shader_clock", + false); + Reqs.addExtension(SPIRV::Extension::SPV_KHR_shader_clock); + Reqs.addCapability(SPIRV::Capability::ShaderClockKHR); + break; case SPIRV::OpFunctionPointerCallINTEL: if (ST.canUseExtension(SPIRV::Extension::SPV_INTEL_function_pointers)) { Reqs.addExtension(SPIRV::Extension::SPV_INTEL_function_pointers); diff --git a/llvm/lib/Target/SPIRV/SPIRVSymbolicOperands.td b/llvm/lib/Target/SPIRV/SPIRVSymbolicOperands.td index 31e19ad8630c..50d327179fa8 100644 --- a/llvm/lib/Target/SPIRV/SPIRVSymbolicOperands.td +++ b/llvm/lib/Target/SPIRV/SPIRVSymbolicOperands.td @@ -413,6 +413,7 @@ defm ImageGatherBiasLodAMD : CapabilityOperand<5009, 0, 0, [], [Shader]>; defm FragmentMaskAMD : CapabilityOperand<5010, 0, 0, [], [Shader]>; defm StencilExportEXT : CapabilityOperand<5013, 0, 0, [], [Shader]>; defm ImageReadWriteLodAMD : CapabilityOperand<5015, 0, 0, [], [Shader]>; +defm ShaderClockKHR : CapabilityOperand<5055, 0, 0, [SPV_KHR_shader_clock], []>; defm SampleMaskOverrideCoverageNV : CapabilityOperand<5249, 0, 0, [], [SampleRateShading]>; defm GeometryShaderPassthroughNV : CapabilityOperand<5251, 0, 0, [], [Geometry]>; defm ShaderViewportIndexLayerEXT : CapabilityOperand<5254, 0, 0, [], [MultiViewport]>; diff --git a/llvm/test/CodeGen/SPIRV/extensions/SPV_KHR_shader_clock/shader_clock.ll b/llvm/test/CodeGen/SPIRV/extensions/SPV_KHR_shader_clock/shader_clock.ll new file mode 100644 index 000000000000..f20c1667421e --- /dev/null +++ b/llvm/test/CodeGen/SPIRV/extensions/SPV_KHR_shader_clock/shader_clock.ll @@ -0,0 +1,59 @@ +; RUN: not llc -O0 -mtriple=spirv64-unknown-unknown %s -o %t.spvt 2>&1 | FileCheck %s --check-prefix=CHECK-ERROR +; RUN: llc -O0 -mtriple=spirv64-unknown-unknown --spirv-ext=+SPV_KHR_shader_clock %s -o - | FileCheck %s +; TODO: %if spirv-tools %{ llc -O0 -mtriple=spirv64-unknown-unknown --spirv-ext=+SPV_KHR_shader_clock %s -o - -filetype=obj | spirv-val %} + +; CHECK-ERROR: LLVM ERROR: clock_read_device: the builtin requires the following SPIR-V extension: SPV_KHR_shader_clock + +; CHECK: OpCapability ShaderClockKHR +; CHECK: OpExtension "SPV_KHR_shader_clock" +; CHECK-DAG: [[uint:%[a-z0-9_]+]] = OpTypeInt 32 +; CHECK-DAG: [[ulong:%[a-z0-9_]+]] = OpTypeInt 64 +; CHECK-DAG: [[v2uint:%[a-z0-9_]+]] = OpTypeVector [[uint]] 2 +; CHECK-DAG: [[uint_1:%[a-z0-9_]+]] = OpConstant [[uint]] 1 +; CHECK-DAG: [[uint_2:%[a-z0-9_]+]] = OpConstant [[uint]] 2 +; CHECK-DAG: [[uint_3:%[a-z0-9_]+]] = OpConstant [[uint]] 3 +; CHECK: OpReadClockKHR [[ulong]] [[uint_1]] +; CHECK: OpReadClockKHR [[ulong]] [[uint_2]] +; CHECK: OpReadClockKHR [[ulong]] [[uint_3]] +; CHECK: OpReadClockKHR [[v2uint]] [[uint_1]] +; CHECK: OpReadClockKHR [[v2uint]] [[uint_2]] +; CHECK: OpReadClockKHR [[v2uint]] [[uint_3]] + +define dso_local spir_kernel void @test_clocks(ptr addrspace(1) nocapture noundef writeonly align 8 %out64, ptr addrspace(1) nocapture noundef writeonly align 8 %outv2) { +entry: + %call = tail call spir_func i64 @_Z17clock_read_devicev() + store i64 %call, ptr addrspace(1) %out64, align 8 + %call1 = tail call spir_func i64 @_Z21clock_read_work_groupv() + %arrayidx2 = getelementptr inbounds i8, ptr addrspace(1) %out64, i32 8 + store i64 %call1, ptr addrspace(1) %arrayidx2, align 8 + %call3 = tail call spir_func i64 @_Z20clock_read_sub_groupv() + %arrayidx4 = getelementptr inbounds i8, ptr addrspace(1) %out64, i32 16 + store i64 %call3, ptr addrspace(1) %arrayidx4, align 8 + %call5 = tail call spir_func <2 x i32> @_Z22clock_read_hilo_devicev() + store <2 x i32> %call5, ptr addrspace(1) %outv2, align 8 + %call7 = tail call spir_func <2 x i32> @_Z26clock_read_hilo_work_groupv() + %arrayidx8 = getelementptr inbounds i8, ptr addrspace(1) %outv2, i32 8 + store <2 x i32> %call7, ptr addrspace(1) %arrayidx8, align 8 + %call9 = tail call spir_func <2 x i32> @_Z25clock_read_hilo_sub_groupv() + %arrayidx10 = getelementptr inbounds i8, ptr addrspace(1) %outv2, i32 16 + store <2 x i32> %call9, ptr addrspace(1) %arrayidx10, align 8 + ret void +} + +; Function Attrs: convergent nounwind +declare spir_func i64 @_Z17clock_read_devicev() local_unnamed_addr + +; Function Attrs: convergent nounwind +declare spir_func i64 @_Z21clock_read_work_groupv() local_unnamed_addr + +; Function Attrs: convergent nounwind +declare spir_func i64 @_Z20clock_read_sub_groupv() local_unnamed_addr + +; Function Attrs: convergent nounwind +declare spir_func <2 x i32> @_Z22clock_read_hilo_devicev() local_unnamed_addr + +; Function Attrs: convergent nounwind +declare spir_func <2 x i32> @_Z26clock_read_hilo_work_groupv() local_unnamed_addr + +; Function Attrs: convergent nounwind +declare spir_func <2 x i32> @_Z25clock_read_hilo_sub_groupv() local_unnamed_addr -- GitLab From c7e9b4918e5bd4936dbc036ba65eae178f5cc994 Mon Sep 17 00:00:00 2001 From: Mateusz Zych Date: Wed, 22 May 2024 11:13:29 +0300 Subject: [PATCH 082/452] [libc++][vector] Inline remaining constructors filling vector with the same value (#82068) Placing physically next to each other remaining constructors filling vector with the same value will make code better, since they all have nearly identical implementation, which needs to be kept in sync. Co-authored-by: Mark de Wever --- libcxx/include/vector | 64 +++++++++++++++++++------------------------ 1 file changed, 28 insertions(+), 36 deletions(-) diff --git a/libcxx/include/vector b/libcxx/include/vector index 976bde9b9048..b190557fb7b7 100644 --- a/libcxx/include/vector +++ b/libcxx/include/vector @@ -424,11 +424,36 @@ public: #endif : __end_cap_(nullptr, __a) { } - _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI explicit vector(size_type __n); + + _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI explicit vector(size_type __n) { + auto __guard = std::__make_exception_guard(__destroy_vector(*this)); + if (__n > 0) { + __vallocate(__n); + __construct_at_end(__n); + } + __guard.__complete(); + } + #if _LIBCPP_STD_VER >= 14 - _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI explicit vector(size_type __n, const allocator_type& __a); + _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI explicit vector(size_type __n, const allocator_type& __a) + : __end_cap_(nullptr, __a) { + auto __guard = std::__make_exception_guard(__destroy_vector(*this)); + if (__n > 0) { + __vallocate(__n); + __construct_at_end(__n); + } + __guard.__complete(); + } #endif - _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI vector(size_type __n, const value_type& __x); + + _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI vector(size_type __n, const value_type& __x) { + auto __guard = std::__make_exception_guard(__destroy_vector(*this)); + if (__n > 0) { + __vallocate(__n); + __construct_at_end(__n, __x); + } + __guard.__complete(); + } template <__enable_if_t<__is_allocator<_Allocator>::value, int> = 0> _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI @@ -1125,39 +1150,6 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 void vector<_Tp, _Allocator>::__append(size_type _ } } -template -_LIBCPP_CONSTEXPR_SINCE_CXX20 vector<_Tp, _Allocator>::vector(size_type __n) { - auto __guard = std::__make_exception_guard(__destroy_vector(*this)); - if (__n > 0) { - __vallocate(__n); - __construct_at_end(__n); - } - __guard.__complete(); -} - -#if _LIBCPP_STD_VER >= 14 -template -_LIBCPP_CONSTEXPR_SINCE_CXX20 vector<_Tp, _Allocator>::vector(size_type __n, const allocator_type& __a) - : __end_cap_(nullptr, __a) { - auto __guard = std::__make_exception_guard(__destroy_vector(*this)); - if (__n > 0) { - __vallocate(__n); - __construct_at_end(__n); - } - __guard.__complete(); -} -#endif - -template -_LIBCPP_CONSTEXPR_SINCE_CXX20 vector<_Tp, _Allocator>::vector(size_type __n, const value_type& __x) { - auto __guard = std::__make_exception_guard(__destroy_vector(*this)); - if (__n > 0) { - __vallocate(__n); - __construct_at_end(__n, __x); - } - __guard.__complete(); -} - template template ::value && -- GitLab From 058e4454e8965f0d96ecbec61395d5a788c37f7c Mon Sep 17 00:00:00 2001 From: ZhangYin Date: Wed, 22 May 2024 16:15:35 +0800 Subject: [PATCH 083/452] [libc++] Add copy functions for class simd/simd_mask (#78935) --- libcxx/docs/Status/ParallelismProjects.csv | 2 + libcxx/include/experimental/__simd/scalar.h | 7 + libcxx/include/experimental/__simd/simd.h | 11 ++ .../include/experimental/__simd/simd_mask.h | 11 ++ libcxx/include/experimental/__simd/vec_ext.h | 11 ++ .../simd/simd.class/simd_copy.pass.cpp | 173 ++++++++++++++++++ .../simd.mask.class/simd_mask_copy.pass.cpp | 127 +++++++++++++ 7 files changed, 342 insertions(+) create mode 100644 libcxx/test/std/experimental/simd/simd.class/simd_copy.pass.cpp create mode 100644 libcxx/test/std/experimental/simd/simd.mask.class/simd_mask_copy.pass.cpp diff --git a/libcxx/docs/Status/ParallelismProjects.csv b/libcxx/docs/Status/ParallelismProjects.csv index 06da008ac5fe..2ddac1e52f02 100644 --- a/libcxx/docs/Status/ParallelismProjects.csv +++ b/libcxx/docs/Status/ParallelismProjects.csv @@ -24,6 +24,7 @@ Section,Description,Dependencies,Assignee,Complete | `[parallel.simd.class] `_, "`simd generate constructor `_", None, Yin Zhang, |Complete| | `[parallel.simd.class] `_, "`simd load constructor `_", None, Yin Zhang, |Complete| | `[parallel.simd.class] `_, "`simd subscript operators `_", None, Yin Zhang, |Complete| +| `[parallel.simd.class] `_, "`simd copy functions `_", None, Yin Zhang, |Complete| | `[parallel.simd.class] `_, "Class template simd implementation", None, Yin Zhang, |In Progress| | `[parallel.simd.nonmembers] `_, "simd non-member operations", None, Yin Zhang, |In Progress| | `[parallel.simd.mask.class] `_, "`Class template simd_mask declaration and alias `_", [parallel.simd.abi], Yin Zhang, |Complete| @@ -33,5 +34,6 @@ Section,Description,Dependencies,Assignee,Complete | `[parallel.simd.mask.class] `_, "`simd_mask implicit type conversion constructor `_", None, Yin Zhang, |Complete| | `[parallel.simd.mask.class] `_, "`simd_mask load constructor `_", None, Yin Zhang, |Complete| | `[parallel.simd.mask.class] `_, "`simd_mask subscript operators `_", None, Yin Zhang, |Complete| +| `[parallel.simd.mask.class] `_, "`simd_mask copy functions `_", None, Yin Zhang, |Complete| | `[parallel.simd.mask.class] `_, "Class template simd_mask implementation", None, Yin Zhang, |In Progress| | `[parallel.simd.mask.nonmembers] `_, "simd_mask non-member operations", None, Yin Zhang, |In Progress| diff --git a/libcxx/include/experimental/__simd/scalar.h b/libcxx/include/experimental/__simd/scalar.h index aff2cd11cfcf..1add4653209a 100644 --- a/libcxx/include/experimental/__simd/scalar.h +++ b/libcxx/include/experimental/__simd/scalar.h @@ -62,6 +62,11 @@ struct __simd_operations<_Tp, simd_abi::__scalar> { static _LIBCPP_HIDE_FROM_ABI void __load(_SimdStorage& __s, const _Up* __mem) noexcept { __s.__data = static_cast<_Tp>(__mem[0]); } + + template + static _LIBCPP_HIDE_FROM_ABI void __store(_SimdStorage __s, _Up* __mem) noexcept { + *__mem = static_cast<_Up>(__s.__data); + } }; template @@ -71,6 +76,8 @@ struct __mask_operations<_Tp, simd_abi::__scalar> { static _LIBCPP_HIDE_FROM_ABI _MaskStorage __broadcast(bool __v) noexcept { return {__v}; } static _LIBCPP_HIDE_FROM_ABI void __load(_MaskStorage& __s, const bool* __mem) noexcept { __s.__data = __mem[0]; } + + static _LIBCPP_HIDE_FROM_ABI void __store(_MaskStorage __s, bool* __mem) noexcept { __mem[0] = __s.__data; } }; } // namespace parallelism_v2 diff --git a/libcxx/include/experimental/__simd/simd.h b/libcxx/include/experimental/__simd/simd.h index db4ebb8e4a38..37e334aad6da 100644 --- a/libcxx/include/experimental/__simd/simd.h +++ b/libcxx/include/experimental/__simd/simd.h @@ -70,6 +70,17 @@ public: _Impl::__load(__s_, _Flags::template __apply(__mem)); } + // copy functions + template && is_simd_flag_type_v<_Flags>, int> = 0> + _LIBCPP_HIDE_FROM_ABI void copy_from(const _Up* __mem, _Flags) { + _Impl::__load(__s_, _Flags::template __apply(__mem)); + } + + template && is_simd_flag_type_v<_Flags>, int> = 0> + _LIBCPP_HIDE_FROM_ABI void copy_to(_Up* __mem, _Flags) const { + _Impl::__store(__s_, _Flags::template __apply(__mem)); + } + // scalar access [simd.subscr] _LIBCPP_HIDE_FROM_ABI reference operator[](size_t __i) noexcept { return reference(__s_, __i); } _LIBCPP_HIDE_FROM_ABI value_type operator[](size_t __i) const noexcept { return __s_.__get(__i); } diff --git a/libcxx/include/experimental/__simd/simd_mask.h b/libcxx/include/experimental/__simd/simd_mask.h index 754db7992683..fd6dee2e28ee 100644 --- a/libcxx/include/experimental/__simd/simd_mask.h +++ b/libcxx/include/experimental/__simd/simd_mask.h @@ -58,6 +58,17 @@ public: _Impl::__load(__s_, _Flags::template __apply(__mem)); } + // copy functions + template , int> = 0> + _LIBCPP_HIDE_FROM_ABI void copy_from(const value_type* __mem, _Flags) { + _Impl::__load(__s_, _Flags::template __apply(__mem)); + } + + template , int> = 0> + _LIBCPP_HIDE_FROM_ABI void copy_to(value_type* __mem, _Flags) const { + _Impl::__store(__s_, _Flags::template __apply(__mem)); + } + // scalar access [simd.mask.subscr] _LIBCPP_HIDE_FROM_ABI reference operator[](size_t __i) noexcept { return reference(__s_, __i); } _LIBCPP_HIDE_FROM_ABI value_type operator[](size_t __i) const noexcept { return __s_.__get(__i); } diff --git a/libcxx/include/experimental/__simd/vec_ext.h b/libcxx/include/experimental/__simd/vec_ext.h index c9423df93cfa..316866b84873 100644 --- a/libcxx/include/experimental/__simd/vec_ext.h +++ b/libcxx/include/experimental/__simd/vec_ext.h @@ -80,6 +80,12 @@ struct __simd_operations<_Tp, simd_abi::__vec_ext<_Np>> { for (size_t __i = 0; __i < _Np; __i++) __s.__data[__i] = static_cast<_Tp>(__mem[__i]); } + + template + static _LIBCPP_HIDE_FROM_ABI void __store(_SimdStorage __s, _Up* __mem) noexcept { + for (size_t __i = 0; __i < _Np; __i++) + __mem[__i] = static_cast<_Up>(__s.__data[__i]); + } }; template @@ -99,6 +105,11 @@ struct __mask_operations<_Tp, simd_abi::__vec_ext<_Np>> { for (size_t __i = 0; __i < _Np; __i++) __s.__data[__i] = experimental::__set_all_bits<_Tp>(__mem[__i]); } + + static _LIBCPP_HIDE_FROM_ABI void __store(_MaskStorage __s, bool* __mem) noexcept { + for (size_t __i = 0; __i < _Np; __i++) + __mem[__i] = static_cast(__s.__data[__i]); + } }; } // namespace parallelism_v2 diff --git a/libcxx/test/std/experimental/simd/simd.class/simd_copy.pass.cpp b/libcxx/test/std/experimental/simd/simd.class/simd_copy.pass.cpp new file mode 100644 index 000000000000..8fcc811f6df3 --- /dev/null +++ b/libcxx/test/std/experimental/simd/simd.class/simd_copy.pass.cpp @@ -0,0 +1,173 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14 + +// FIXME: Fatal error with following targets (remove XFAIL when fixed): +// Pass-by-value arguments with alignment greater than register width are not supported. +// XFAIL: target=powerpc{{.*}}-ibm-aix7.2.5.7 + +// +// +// [simd.class] +// template void copy_from(const U* mem, Flags); +// template void copy_to(U* mem, Flags) const; + +#include "../test_utils.h" + +namespace ex = std::experimental::parallelism_v2; + +template +struct ElementAlignedCopyFromHelper { + template + void operator()() const { + U buffer[array_size]; + for (size_t i = 0; i < array_size; ++i) + buffer[i] = static_cast(i); + ex::simd origin_simd; + origin_simd.copy_from(buffer, ex::element_aligned_tag()); + assert_simd_values_equal(origin_simd, buffer); + } +}; + +template +struct VectorAlignedCopyFromHelper { + template + void operator()() const { + alignas(ex::memory_alignment_v, U>) U buffer[array_size]; + for (size_t i = 0; i < array_size; ++i) + buffer[i] = static_cast(i); + ex::simd origin_simd; + origin_simd.copy_from(buffer, ex::vector_aligned_tag()); + assert_simd_values_equal(origin_simd, buffer); + } +}; + +template +struct OveralignedCopyFromHelper { + template + void operator()() const { + alignas(bit_ceil(sizeof(U) + 1)) U buffer[array_size]; + for (size_t i = 0; i < array_size; ++i) + buffer[i] = static_cast(i); + ex::simd origin_simd; + origin_simd.copy_from(buffer, ex::overaligned_tag()); + assert_simd_values_equal(origin_simd, buffer); + } +}; + +template +struct CheckSimdCopyFrom { + template + void operator()() { + constexpr std::size_t array_size = ex::simd_size_v; + + types::for_each(simd_test_types(), ElementAlignedCopyFromHelper()); + types::for_each(simd_test_types(), VectorAlignedCopyFromHelper()); + types::for_each(simd_test_types(), OveralignedCopyFromHelper()); + } +}; + +template +struct ElementAlignedCopyToHelper { + template + void operator()() const { + U buffer[array_size]; + ex::simd origin_simd([](T i) { return i; }); + origin_simd.copy_to(buffer, ex::element_aligned_tag()); + assert_simd_values_equal(origin_simd, buffer); + } +}; + +template +struct VectorAlignedCopyToHelper { + template + void operator()() const { + alignas(ex::memory_alignment_v, U>) U buffer[array_size]; + ex::simd origin_simd([](T i) { return i; }); + origin_simd.copy_to(buffer, ex::vector_aligned_tag()); + assert_simd_values_equal(origin_simd, buffer); + } +}; + +template +struct OveralignedCopyToHelper { + template + void operator()() const { + alignas(bit_ceil(sizeof(U) + 1)) U buffer[array_size]; + ex::simd origin_simd([](T i) { return i; }); + origin_simd.copy_to(buffer, ex::overaligned_tag()); + assert_simd_values_equal(origin_simd, buffer); + } +}; + +template +struct CheckSimdCopyTo { + template + void operator()() { + constexpr std::size_t array_size = ex::simd_size_v; + + types::for_each(simd_test_types(), ElementAlignedCopyToHelper()); + types::for_each(simd_test_types(), VectorAlignedCopyToHelper()); + types::for_each(simd_test_types(), OveralignedCopyToHelper()); + } +}; + +template , class = void> +struct has_copy_from : std::false_type {}; + +template +struct has_copy_from>().copy_from( + std::declval(), std::declval()))>> : std::true_type {}; + +template , class = void> +struct has_copy_to : std::false_type {}; + +template +struct has_copy_to< + U, + T, + Flags, + SimdAbi, + std::void_t>().copy_to(std::declval(), std::declval()))>> + : std::true_type {}; + +template +struct CheckSimdCopyTraits { + template + void operator()() { + // These functions shall not participate in overload resolution unless + // is_simd_flag_type_v is true, and + // U is a vectorizable type. + static_assert(has_copy_from::value); + static_assert(has_copy_to::value); + + // is_simd_flag_type_v is false + static_assert(!has_copy_from::value); + static_assert(!has_copy_to::value); + static_assert(!has_copy_from::value); + static_assert(!has_copy_to::value); + + // U is not a vectorizable type. + static_assert(!has_copy_from::value); + static_assert(!has_copy_to::value); + static_assert(!has_copy_from::value); + static_assert(!has_copy_to::value); + } +}; + +int main(int, char**) { + test_all_simd_abi(); + test_all_simd_abi(); + test_all_simd_abi(); + return 0; +} diff --git a/libcxx/test/std/experimental/simd/simd.mask.class/simd_mask_copy.pass.cpp b/libcxx/test/std/experimental/simd/simd.mask.class/simd_mask_copy.pass.cpp new file mode 100644 index 000000000000..0c3b4c9ea6d5 --- /dev/null +++ b/libcxx/test/std/experimental/simd/simd.mask.class/simd_mask_copy.pass.cpp @@ -0,0 +1,127 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14 + +// +// +// [simd.class] +// template void copy_from(const value_type* mem, Flags); +// template void copy_to(value_type* mem, Flags); + +#include "../test_utils.h" + +namespace ex = std::experimental::parallelism_v2; + +template +struct CheckSimdMaskCopyFrom { + template + void operator()() { + constexpr std::size_t array_size = ex::simd_size_v; + + // element aligned tag + constexpr std::size_t element_alignas_size = alignof(bool); + alignas(element_alignas_size) bool element_buffer[array_size]; + for (size_t i = 0; i < array_size; ++i) + element_buffer[i] = static_cast(i % 2); + ex::simd_mask element_mask; + element_mask.copy_from(element_buffer, ex::element_aligned_tag()); + assert_simd_mask_values_equal(element_mask, element_buffer); + + // vector aligned tag + constexpr std::size_t vector_alignas_size = ex::memory_alignment_v>; + alignas(vector_alignas_size) bool vector_buffer[array_size]; + for (size_t i = 0; i < array_size; ++i) + vector_buffer[i] = static_cast(i % 2); + ex::simd_mask vector_mask; + vector_mask.copy_from(vector_buffer, ex::vector_aligned_tag()); + assert_simd_mask_values_equal(vector_mask, vector_buffer); + + // overaligned tag + constexpr std::size_t over_alignas_size = bit_ceil(sizeof(bool) + 1); + alignas(over_alignas_size) bool overaligned_buffer[array_size]; + for (size_t i = 0; i < array_size; ++i) + overaligned_buffer[i] = static_cast(i % 2); + ex::simd_mask overaligned_mask; + overaligned_mask.copy_from(overaligned_buffer, ex::overaligned_tag()); + assert_simd_mask_values_equal(overaligned_mask, overaligned_buffer); + } +}; + +template +struct CheckSimdMaskCopyTo { + template + void operator()() { + constexpr std::size_t array_size = ex::simd_size_v; + + // element aligned tag + constexpr std::size_t element_alignas_size = alignof(bool); + alignas(element_alignas_size) bool element_buffer[array_size]; + ex::simd_mask element_mask(true); + element_mask.copy_to(element_buffer, ex::element_aligned_tag()); + assert_simd_mask_values_equal(element_mask, element_buffer); + + // vector aligned tag + constexpr std::size_t vector_alignas_size = ex::memory_alignment_v>; + alignas(vector_alignas_size) bool vector_buffer[array_size]; + ex::simd_mask vector_mask(false); + vector_mask.copy_to(vector_buffer, ex::vector_aligned_tag()); + assert_simd_mask_values_equal(vector_mask, vector_buffer); + + // overaligned tag + constexpr std::size_t over_alignas_size = bit_ceil(sizeof(bool) + 1); + alignas(over_alignas_size) bool overaligned_buffer[array_size]; + ex::simd_mask overaligned_mask(true); + overaligned_mask.copy_to(overaligned_buffer, ex::overaligned_tag()); + assert_simd_mask_values_equal(overaligned_mask, overaligned_buffer); + } +}; + +template , class = void> +struct has_copy_from : std::false_type {}; + +template +struct has_copy_from>().copy_from( + std::declval(), std::declval()))>> : std::true_type {}; + +template , class = void> +struct has_copy_to : std::false_type {}; + +template +struct has_copy_to>().copy_to( + std::declval(), std::declval()))>> : std::true_type {}; + +template +struct CheckSimdMaskCopyTraits { + template + void operator()() { + // These functions shall not participate in overload resolution unless + // is_simd_flag_type_v is true + static_assert(has_copy_from::value); + static_assert(has_copy_to::value); + + // is_simd_flag_type_v is false + static_assert(!has_copy_from::value); + static_assert(!has_copy_to::value); + static_assert(!has_copy_from::value); + static_assert(!has_copy_to::value); + } +}; + +int main(int, char**) { + test_all_simd_abi(); + test_all_simd_abi(); + test_all_simd_abi(); + return 0; +} -- GitLab From a640a2e0205fc23a27913d3e7c69c7cc60e4f7b9 Mon Sep 17 00:00:00 2001 From: Vlad Serebrennikov Date: Wed, 22 May 2024 12:54:19 +0400 Subject: [PATCH 084/452] [clang] Introduce `SemaRISCV` (#92682) This patch moves `Sema` functions that are specific for RISC-V into the new `SemaRISCV` class. This continues previous efforts to split `Sema` up. Additional context can be found in https://github.com/llvm/llvm-project/pull/84184. This PR is somewhat different from previous PRs on this topic: 1. Splitting out target-specific functions wasn't previously discussed. It felt quite natural to do, though. 2. I had to make some static function in `SemaChecking.cpp` member functions of `Sema` in order to use them in `SemaRISCV`. 3. I dropped "RISCV" from identifiers, but decided to leave "RVV" (RISC-V "V" vector extensions) intact. I think it's an idiomatic abbreviation at this point, but I'm open to input from contributors in that area. 4. I repurposed `SemaRISCVVectorLookup.cpp` for `SemaRISCV`. I think this was a successful experiment, which both helps the goal of splitting `Sema` up, and shows a way to approach `SemaChecking.cpp`, which I wasn't sure how to approach before. As we move more target-specific function out of there, we'll gradually make the checking "framework" inside `SemaChecking.cpp` public, which is currently a whole bunch of static functions. This would enable us to move more functions outside of `SemaChecking.cpp`. --- clang/include/clang/Sema/Sema.h | 66 +- clang/include/clang/Sema/SemaRISCV.h | 52 ++ clang/lib/Parse/ParsePragma.cpp | 5 +- clang/lib/Sema/Sema.cpp | 4 +- clang/lib/Sema/SemaCast.cpp | 5 +- clang/lib/Sema/SemaChecking.cpp | 1047 ++------------------------ clang/lib/Sema/SemaDecl.cpp | 5 +- clang/lib/Sema/SemaExpr.cpp | 21 - clang/lib/Sema/SemaLookup.cpp | 11 +- clang/lib/Sema/SemaRISCV.cpp | 939 ++++++++++++++++++++++- 10 files changed, 1104 insertions(+), 1051 deletions(-) create mode 100644 clang/include/clang/Sema/SemaRISCV.h diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index 39da728c616c..4e628b21e65e 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -175,6 +175,7 @@ class SemaObjC; class SemaOpenACC; class SemaOpenMP; class SemaPseudoObject; +class SemaRISCV; class SemaSYCL; class StandardConversionSequence; class Stmt; @@ -491,7 +492,6 @@ class Sema final : public SemaBase { // 29. Constraints and Concepts (SemaConcept.cpp) // 30. Types (SemaType.cpp) // 31. FixIt Helpers (SemaFixItUtils.cpp) - // 32. Name Lookup for RISC-V Vector Intrinsic (SemaRISCVVectorLookup.cpp) /// \name Semantic Analysis /// Implementations are in Sema.cpp @@ -1027,6 +1027,11 @@ public: return *PseudoObjectPtr; } + SemaRISCV &RISCV() { + assert(RISCVPtr); + return *RISCVPtr; + } + SemaSYCL &SYCL() { assert(SYCLPtr); return *SYCLPtr; @@ -1069,6 +1074,7 @@ private: std::unique_ptr OpenACCPtr; std::unique_ptr OpenMPPtr; std::unique_ptr PseudoObjectPtr; + std::unique_ptr RISCVPtr; std::unique_ptr SYCLPtr; ///@} @@ -2044,6 +2050,23 @@ public: void CheckConstrainedAuto(const AutoType *AutoT, SourceLocation Loc); + bool BuiltinConstantArg(CallExpr *TheCall, int ArgNum, llvm::APSInt &Result); + bool BuiltinConstantArgRange(CallExpr *TheCall, int ArgNum, int Low, int High, + bool RangeIsError = true); + bool BuiltinConstantArgMultiple(CallExpr *TheCall, int ArgNum, + unsigned Multiple); + bool BuiltinConstantArgPower2(CallExpr *TheCall, int ArgNum); + bool BuiltinConstantArgShiftedByte(CallExpr *TheCall, int ArgNum, + unsigned ArgBits); + bool BuiltinConstantArgShiftedByteOrXXFF(CallExpr *TheCall, int ArgNum, + unsigned ArgBits); + + bool checkArgCountAtLeast(CallExpr *Call, unsigned MinArgCount); + bool checkArgCountAtMost(CallExpr *Call, unsigned MaxArgCount); + bool checkArgCountRange(CallExpr *Call, unsigned MinArgCount, + unsigned MaxArgCount); + bool checkArgCount(CallExpr *Call, unsigned DesiredArgCount); + private: void CheckArrayAccess(const Expr *BaseExpr, const Expr *IndexExpr, const ArraySubscriptExpr *ASE = nullptr, @@ -2112,11 +2135,7 @@ private: bool CheckPPCBuiltinFunctionCall(const TargetInfo &TI, unsigned BuiltinID, CallExpr *TheCall); bool CheckAMDGCNBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall); - bool CheckRISCVLMUL(CallExpr *TheCall, unsigned ArgNum); - bool CheckRISCVBuiltinFunctionCall(const TargetInfo &TI, unsigned BuiltinID, - CallExpr *TheCall); - void checkRVVTypeSupport(QualType Ty, SourceLocation Loc, Decl *D, - const llvm::StringMap &FeatureMap); + bool CheckLoongArchBuiltinFunctionCall(const TargetInfo &TI, unsigned BuiltinID, CallExpr *TheCall); bool CheckWebAssemblyBuiltinFunctionCall(const TargetInfo &TI, @@ -2146,16 +2165,6 @@ private: ExprResult BuiltinNontemporalOverloaded(ExprResult TheCallResult); ExprResult AtomicOpsOverloaded(ExprResult TheCallResult, AtomicExpr::AtomicOp Op); - bool BuiltinConstantArg(CallExpr *TheCall, int ArgNum, llvm::APSInt &Result); - bool BuiltinConstantArgRange(CallExpr *TheCall, int ArgNum, int Low, int High, - bool RangeIsError = true); - bool BuiltinConstantArgMultiple(CallExpr *TheCall, int ArgNum, - unsigned Multiple); - bool BuiltinConstantArgPower2(CallExpr *TheCall, int ArgNum); - bool BuiltinConstantArgShiftedByte(CallExpr *TheCall, int ArgNum, - unsigned ArgBits); - bool BuiltinConstantArgShiftedByteOrXXFF(CallExpr *TheCall, int ArgNum, - unsigned ArgBits); bool BuiltinARMSpecialReg(unsigned BuiltinID, CallExpr *TheCall, int ArgNum, unsigned ExpectedFieldNum, bool AllowName); bool BuiltinARMMemoryTaggingCall(unsigned BuiltinID, CallExpr *TheCall); @@ -5890,7 +5899,6 @@ public: SourceLocation Loc, bool IsCompAssign); bool isValidSveBitcast(QualType srcType, QualType destType); - bool isValidRVVBitcast(QualType srcType, QualType destType); bool areMatrixTypesOfTheSameDimension(QualType srcTy, QualType destTy); @@ -11686,27 +11694,6 @@ public: /// Triggered by declaration-attribute processing. void ProcessAPINotes(Decl *D); - ///@} - // - // - // ------------------------------------------------------------------------- - // - // - - /// \name Name Lookup for RISC-V Vector Intrinsic - /// Implementations are in SemaRISCVVectorLookup.cpp - ///@{ - -public: - /// Indicate RISC-V vector builtin functions enabled or not. - bool DeclareRISCVVBuiltins = false; - - /// Indicate RISC-V SiFive vector builtin functions enabled or not. - bool DeclareRISCVSiFiveVectorBuiltins = false; - -private: - std::unique_ptr RVIntrinsicManager; - ///@} }; @@ -11729,9 +11716,6 @@ void Sema::PragmaStack::Act(SourceLocation PragmaLocation, PragmaMsStackAction Action, llvm::StringRef StackSlotLabel, AlignPackInfo Value); - -std::unique_ptr -CreateRISCVIntrinsicManager(Sema &S); } // end namespace clang #endif diff --git a/clang/include/clang/Sema/SemaRISCV.h b/clang/include/clang/Sema/SemaRISCV.h new file mode 100644 index 000000000000..b6dd81f8d4d8 --- /dev/null +++ b/clang/include/clang/Sema/SemaRISCV.h @@ -0,0 +1,52 @@ +//===----- SemaRISCV.h ---- RISC-V target-specific routines ---*- C++ -*---===// +// +// 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 +// +//===----------------------------------------------------------------------===// +/// \file +/// This file declares semantic analysis functions specific to RISC-V. +/// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_SEMA_SEMARISCV_H +#define LLVM_CLANG_SEMA_SEMARISCV_H + +#include "clang/AST/DeclBase.h" +#include "clang/AST/Expr.h" +#include "clang/AST/Type.h" +#include "clang/Basic/SourceLocation.h" +#include "clang/Basic/TargetInfo.h" +#include "clang/Sema/RISCVIntrinsicManager.h" +#include "clang/Sema/SemaBase.h" +#include "llvm/ADT/StringMap.h" +#include + +namespace clang { +class SemaRISCV : public SemaBase { +public: + SemaRISCV(Sema &S); + + bool CheckLMUL(CallExpr *TheCall, unsigned ArgNum); + bool CheckBuiltinFunctionCall(const TargetInfo &TI, unsigned BuiltinID, + CallExpr *TheCall); + void checkRVVTypeSupport(QualType Ty, SourceLocation Loc, Decl *D, + const llvm::StringMap &FeatureMap); + + bool isValidRVVBitcast(QualType srcType, QualType destType); + + /// Indicate RISC-V vector builtin functions enabled or not. + bool DeclareRVVBuiltins = false; + + /// Indicate RISC-V SiFive vector builtin functions enabled or not. + bool DeclareSiFiveVectorBuiltins = false; + + std::unique_ptr IntrinsicManager; +}; + +std::unique_ptr +CreateRISCVIntrinsicManager(Sema &S); +} // namespace clang + +#endif // LLVM_CLANG_SEMA_SEMARISCV_H diff --git a/clang/lib/Parse/ParsePragma.cpp b/clang/lib/Parse/ParsePragma.cpp index 643fdac287d1..cc6f18b5b319 100644 --- a/clang/lib/Parse/ParsePragma.cpp +++ b/clang/lib/Parse/ParsePragma.cpp @@ -23,6 +23,7 @@ #include "clang/Sema/Scope.h" #include "clang/Sema/SemaCUDA.h" #include "clang/Sema/SemaCodeCompletion.h" +#include "clang/Sema/SemaRISCV.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/StringSwitch.h" #include @@ -4154,7 +4155,7 @@ void PragmaRISCVHandler::HandlePragma(Preprocessor &PP, } if (II->isStr("vector")) - Actions.DeclareRISCVVBuiltins = true; + Actions.RISCV().DeclareRVVBuiltins = true; else if (II->isStr("sifive_vector")) - Actions.DeclareRISCVSiFiveVectorBuiltins = true; + Actions.RISCV().DeclareSiFiveVectorBuiltins = true; } diff --git a/clang/lib/Sema/Sema.cpp b/clang/lib/Sema/Sema.cpp index 2c5774da3f66..f6317f10b184 100644 --- a/clang/lib/Sema/Sema.cpp +++ b/clang/lib/Sema/Sema.cpp @@ -50,6 +50,7 @@ #include "clang/Sema/SemaOpenACC.h" #include "clang/Sema/SemaOpenMP.h" #include "clang/Sema/SemaPseudoObject.h" +#include "clang/Sema/SemaRISCV.h" #include "clang/Sema/SemaSYCL.h" #include "clang/Sema/TemplateDeduction.h" #include "clang/Sema/TemplateInstCallback.h" @@ -212,6 +213,7 @@ Sema::Sema(Preprocessor &pp, ASTContext &ctxt, ASTConsumer &consumer, OpenACCPtr(std::make_unique(*this)), OpenMPPtr(std::make_unique(*this)), PseudoObjectPtr(std::make_unique(*this)), + RISCVPtr(std::make_unique(*this)), SYCLPtr(std::make_unique(*this)), MSPointerToMemberRepresentationMethod( LangOpts.getMSPointerToMemberRepresentationMethod()), @@ -2051,7 +2053,7 @@ void Sema::checkTypeSupport(QualType Ty, SourceLocation Loc, ValueDecl *D) { if (TI.hasRISCVVTypes() && Ty->isRVVSizelessBuiltinType() && FD) { llvm::StringMap CallerFeatureMap; Context.getFunctionFeatureMap(CallerFeatureMap, FD); - checkRVVTypeSupport(Ty, Loc, D, CallerFeatureMap); + RISCV().checkRVVTypeSupport(Ty, Loc, D, CallerFeatureMap); } // Don't allow SVE types in functions without a SVE target. diff --git a/clang/lib/Sema/SemaCast.cpp b/clang/lib/Sema/SemaCast.cpp index 483ec7e36eae..7db6b1dfe923 100644 --- a/clang/lib/Sema/SemaCast.cpp +++ b/clang/lib/Sema/SemaCast.cpp @@ -25,6 +25,7 @@ #include "clang/Sema/Initialization.h" #include "clang/Sema/SemaInternal.h" #include "clang/Sema/SemaObjC.h" +#include "clang/Sema/SemaRISCV.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringExtras.h" #include @@ -2391,7 +2392,7 @@ static TryCastResult TryReinterpretCast(Sema &Self, ExprResult &SrcExpr, } // Allow bitcasting between SVE VLATs and VLSTs, and vice-versa. - if (Self.isValidRVVBitcast(SrcType, DestType)) { + if (Self.RISCV().isValidRVVBitcast(SrcType, DestType)) { Kind = CK_BitCast; return TC_Success; } @@ -3002,7 +3003,7 @@ void CastOperation::CheckCStyleCast() { // Allow bitcasting between compatible RVV vector types. if ((SrcType->isVectorType() || DestType->isVectorType()) && - Self.isValidRVVBitcast(SrcType, DestType)) { + Self.RISCV().isValidRVVBitcast(SrcType, DestType)) { Kind = CK_BitCast; return; } diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp index f2dc8e9dd005..8c08bf7510c8 100644 --- a/clang/lib/Sema/SemaChecking.cpp +++ b/clang/lib/Sema/SemaChecking.cpp @@ -63,6 +63,7 @@ #include "clang/Sema/Sema.h" #include "clang/Sema/SemaInternal.h" #include "clang/Sema/SemaObjC.h" +#include "clang/Sema/SemaRISCV.h" #include "llvm/ADT/APFloat.h" #include "llvm/ADT/APInt.h" #include "llvm/ADT/APSInt.h" @@ -120,13 +121,12 @@ static constexpr unsigned short combineFAPK(Sema::FormatArgumentPassingKind A, /// Checks that a call expression's argument count is at least the desired /// number. This is useful when doing custom type-checking on a variadic /// function. Returns true on error. -static bool checkArgCountAtLeast(Sema &S, CallExpr *Call, - unsigned MinArgCount) { +bool Sema::checkArgCountAtLeast(CallExpr *Call, unsigned MinArgCount) { unsigned ArgCount = Call->getNumArgs(); if (ArgCount >= MinArgCount) return false; - return S.Diag(Call->getEndLoc(), diag::err_typecheck_call_too_few_args) + return Diag(Call->getEndLoc(), diag::err_typecheck_call_too_few_args) << 0 /*function call*/ << MinArgCount << ArgCount << /*is non object*/ 0 << Call->getSourceRange(); } @@ -134,12 +134,11 @@ static bool checkArgCountAtLeast(Sema &S, CallExpr *Call, /// Checks that a call expression's argument count is at most the desired /// number. This is useful when doing custom type-checking on a variadic /// function. Returns true on error. -static bool checkArgCountAtMost(Sema &S, CallExpr *Call, unsigned MaxArgCount) { +bool Sema::checkArgCountAtMost(CallExpr *Call, unsigned MaxArgCount) { unsigned ArgCount = Call->getNumArgs(); if (ArgCount <= MaxArgCount) return false; - return S.Diag(Call->getEndLoc(), - diag::err_typecheck_call_too_many_args_at_most) + return Diag(Call->getEndLoc(), diag::err_typecheck_call_too_many_args_at_most) << 0 /*function call*/ << MaxArgCount << ArgCount << /*is non object*/ 0 << Call->getSourceRange(); } @@ -147,20 +146,20 @@ static bool checkArgCountAtMost(Sema &S, CallExpr *Call, unsigned MaxArgCount) { /// Checks that a call expression's argument count is in the desired range. This /// is useful when doing custom type-checking on a variadic function. Returns /// true on error. -static bool checkArgCountRange(Sema &S, CallExpr *Call, unsigned MinArgCount, - unsigned MaxArgCount) { - return checkArgCountAtLeast(S, Call, MinArgCount) || - checkArgCountAtMost(S, Call, MaxArgCount); +bool Sema::checkArgCountRange(CallExpr *Call, unsigned MinArgCount, + unsigned MaxArgCount) { + return checkArgCountAtLeast(Call, MinArgCount) || + checkArgCountAtMost(Call, MaxArgCount); } /// Checks that a call expression's argument count is the desired number. /// This is useful when doing custom type-checking. Returns true on error. -static bool checkArgCount(Sema &S, CallExpr *Call, unsigned DesiredArgCount) { +bool Sema::checkArgCount(CallExpr *Call, unsigned DesiredArgCount) { unsigned ArgCount = Call->getNumArgs(); if (ArgCount == DesiredArgCount) return false; - if (checkArgCountAtLeast(S, Call, DesiredArgCount)) + if (checkArgCountAtLeast(Call, DesiredArgCount)) return true; assert(ArgCount > DesiredArgCount && "should have diagnosed this"); @@ -168,7 +167,7 @@ static bool checkArgCount(Sema &S, CallExpr *Call, unsigned DesiredArgCount) { SourceRange Range(Call->getArg(DesiredArgCount)->getBeginLoc(), Call->getArg(ArgCount - 1)->getEndLoc()); - return S.Diag(Range.getBegin(), diag::err_typecheck_call_too_many_args) + return Diag(Range.getBegin(), diag::err_typecheck_call_too_many_args) << 0 /*function call*/ << DesiredArgCount << ArgCount << /*is non object*/ 0 << Call->getArg(1)->getSourceRange(); } @@ -190,7 +189,7 @@ static bool convertArgumentToType(Sema &S, Expr *&Value, QualType Ty) { /// Check that the first argument to __builtin_annotation is an integer /// and the second argument is a non-wide string literal. static bool BuiltinAnnotation(Sema &S, CallExpr *TheCall) { - if (checkArgCount(S, TheCall, 2)) + if (S.checkArgCount(TheCall, 2)) return true; // First argument should be an integer. @@ -240,7 +239,7 @@ static bool BuiltinMSVCAnnotation(Sema &S, CallExpr *TheCall) { /// Check that the argument to __builtin_addressof is a glvalue, and set the /// result type to the corresponding pointer type. static bool BuiltinAddressof(Sema &S, CallExpr *TheCall) { - if (checkArgCount(S, TheCall, 1)) + if (S.checkArgCount(TheCall, 1)) return true; ExprResult Arg(TheCall->getArg(0)); @@ -255,7 +254,7 @@ static bool BuiltinAddressof(Sema &S, CallExpr *TheCall) { /// Check that the argument to __builtin_function_start is a function. static bool BuiltinFunctionStart(Sema &S, CallExpr *TheCall) { - if (checkArgCount(S, TheCall, 1)) + if (S.checkArgCount(TheCall, 1)) return true; ExprResult Arg = S.DefaultFunctionArrayLvalueConversion(TheCall->getArg(0)); @@ -279,7 +278,7 @@ static bool BuiltinFunctionStart(Sema &S, CallExpr *TheCall) { /// Check the number of arguments and set the result type to /// the argument type. static bool BuiltinPreserveAI(Sema &S, CallExpr *TheCall) { - if (checkArgCount(S, TheCall, 1)) + if (S.checkArgCount(TheCall, 1)) return true; TheCall->setType(TheCall->getArg(0)->getType()); @@ -290,7 +289,7 @@ static bool BuiltinPreserveAI(Sema &S, CallExpr *TheCall) { /// __builtin_aligned_{up,down}(value, alignment) is an integer or a pointer /// type (but not a function pointer) and that the alignment is a power-of-two. static bool BuiltinAlignment(Sema &S, CallExpr *TheCall, unsigned ID) { - if (checkArgCount(S, TheCall, 2)) + if (S.checkArgCount(TheCall, 2)) return true; clang::Expr *Source = TheCall->getArg(0); @@ -368,7 +367,7 @@ static bool BuiltinAlignment(Sema &S, CallExpr *TheCall, unsigned ID) { } static bool BuiltinOverflow(Sema &S, CallExpr *TheCall, unsigned BuiltinID) { - if (checkArgCount(S, TheCall, 3)) + if (S.checkArgCount(TheCall, 3)) return true; std::pair Builtins[] = { @@ -696,7 +695,7 @@ struct BuiltinDumpStructGenerator { } // namespace static ExprResult BuiltinDumpStruct(Sema &S, CallExpr *TheCall) { - if (checkArgCountAtLeast(S, TheCall, 2)) + if (S.checkArgCountAtLeast(TheCall, 2)) return ExprError(); ExprResult PtrArgResult = S.DefaultLvalueConversion(TheCall->getArg(0)); @@ -762,7 +761,7 @@ static ExprResult BuiltinDumpStruct(Sema &S, CallExpr *TheCall) { } static bool BuiltinCallWithStaticChain(Sema &S, CallExpr *BuiltinCall) { - if (checkArgCount(S, BuiltinCall, 2)) + if (S.checkArgCount(BuiltinCall, 2)) return true; SourceLocation BuiltinLoc = BuiltinCall->getBeginLoc(); @@ -1504,7 +1503,7 @@ static bool checkOpenCLSubgroupExt(Sema &S, CallExpr *Call) { } static bool OpenCLBuiltinNDRangeAndBlock(Sema &S, CallExpr *TheCall) { - if (checkArgCount(S, TheCall, 2)) + if (S.checkArgCount(TheCall, 2)) return true; if (checkOpenCLSubgroupExt(S, TheCall)) @@ -1531,7 +1530,7 @@ static bool OpenCLBuiltinNDRangeAndBlock(Sema &S, CallExpr *TheCall) { /// get_kernel_work_group_size /// and get_kernel_preferred_work_group_size_multiple builtin functions. static bool OpenCLBuiltinKernelWorkGroupSize(Sema &S, CallExpr *TheCall) { - if (checkArgCount(S, TheCall, 1)) + if (S.checkArgCount(TheCall, 1)) return true; Expr *BlockArg = TheCall->getArg(0); @@ -1861,7 +1860,7 @@ static bool BuiltinRWPipe(Sema &S, CallExpr *Call) { // \param Call The call to the builtin function to be analyzed. // \return True if a semantic error was found, false otherwise. static bool BuiltinReserveRWPipe(Sema &S, CallExpr *Call) { - if (checkArgCount(S, Call, 2)) + if (S.checkArgCount(Call, 2)) return true; if (checkOpenCLPipeArg(S, Call)) @@ -1890,7 +1889,7 @@ static bool BuiltinReserveRWPipe(Sema &S, CallExpr *Call) { // \param Call The call to the builtin function to be analyzed. // \return True if a semantic error was found, false otherwise. static bool BuiltinCommitRWPipe(Sema &S, CallExpr *Call) { - if (checkArgCount(S, Call, 2)) + if (S.checkArgCount(Call, 2)) return true; if (checkOpenCLPipeArg(S, Call)) @@ -1913,7 +1912,7 @@ static bool BuiltinCommitRWPipe(Sema &S, CallExpr *Call) { // \param Call The call to the builtin function to be analyzed. // \return True if a semantic error was found, false otherwise. static bool BuiltinPipePackets(Sema &S, CallExpr *Call) { - if (checkArgCount(S, Call, 1)) + if (S.checkArgCount(Call, 1)) return true; if (!Call->getArg(0)->getType()->isPipeType()) { @@ -1932,7 +1931,7 @@ static bool BuiltinPipePackets(Sema &S, CallExpr *Call) { // \param Call A pointer to the builtin call. // \return True if a semantic error has been found, false otherwise. static bool OpenCLBuiltinToAddr(Sema &S, unsigned BuiltinID, CallExpr *Call) { - if (checkArgCount(S, Call, 1)) + if (S.checkArgCount(Call, 1)) return true; auto RT = Call->getArg(0)->getType(); @@ -2087,7 +2086,7 @@ static bool checkPointerAuthValue(Sema &S, Expr *&Arg, } static ExprResult PointerAuthStrip(Sema &S, CallExpr *Call) { - if (checkArgCount(S, Call, 2)) + if (S.checkArgCount(Call, 2)) return ExprError(); if (checkPointerAuthEnabled(S, Call)) return ExprError(); @@ -2100,7 +2099,7 @@ static ExprResult PointerAuthStrip(Sema &S, CallExpr *Call) { } static ExprResult PointerAuthBlendDiscriminator(Sema &S, CallExpr *Call) { - if (checkArgCount(S, Call, 2)) + if (S.checkArgCount(Call, 2)) return ExprError(); if (checkPointerAuthEnabled(S, Call)) return ExprError(); @@ -2113,7 +2112,7 @@ static ExprResult PointerAuthBlendDiscriminator(Sema &S, CallExpr *Call) { } static ExprResult PointerAuthSignGenericData(Sema &S, CallExpr *Call) { - if (checkArgCount(S, Call, 2)) + if (S.checkArgCount(Call, 2)) return ExprError(); if (checkPointerAuthEnabled(S, Call)) return ExprError(); @@ -2127,7 +2126,7 @@ static ExprResult PointerAuthSignGenericData(Sema &S, CallExpr *Call) { static ExprResult PointerAuthSignOrAuth(Sema &S, CallExpr *Call, PointerAuthOpKind OpKind) { - if (checkArgCount(S, Call, 3)) + if (S.checkArgCount(Call, 3)) return ExprError(); if (checkPointerAuthEnabled(S, Call)) return ExprError(); @@ -2141,7 +2140,7 @@ static ExprResult PointerAuthSignOrAuth(Sema &S, CallExpr *Call, } static ExprResult PointerAuthAuthAndResign(Sema &S, CallExpr *Call) { - if (checkArgCount(S, Call, 5)) + if (S.checkArgCount(Call, 5)) return ExprError(); if (checkPointerAuthEnabled(S, Call)) return ExprError(); @@ -2157,7 +2156,7 @@ static ExprResult PointerAuthAuthAndResign(Sema &S, CallExpr *Call) { } static ExprResult BuiltinLaunder(Sema &S, CallExpr *TheCall) { - if (checkArgCount(S, TheCall, 1)) + if (S.checkArgCount(TheCall, 1)) return ExprError(); // Compute __builtin_launder's parameter type from the argument. @@ -2288,7 +2287,7 @@ bool Sema::CheckTSBuiltinFunctionCall(const TargetInfo &TI, unsigned BuiltinID, return CheckAMDGCNBuiltinFunctionCall(BuiltinID, TheCall); case llvm::Triple::riscv32: case llvm::Triple::riscv64: - return CheckRISCVBuiltinFunctionCall(TI, BuiltinID, TheCall); + return RISCV().CheckBuiltinFunctionCall(TI, BuiltinID, TheCall); case llvm::Triple::loongarch32: case llvm::Triple::loongarch64: return CheckLoongArchBuiltinFunctionCall(TI, BuiltinID, TheCall); @@ -2377,7 +2376,7 @@ static bool BuiltinCpu(Sema &S, const TargetInfo &TI, CallExpr *TheCall, /// Checks that __builtin_popcountg was called with a single argument, which is /// an unsigned integer. static bool BuiltinPopcountg(Sema &S, CallExpr *TheCall) { - if (checkArgCount(S, TheCall, 1)) + if (S.checkArgCount(TheCall, 1)) return true; ExprResult ArgRes = S.DefaultLvalueConversion(TheCall->getArg(0)); @@ -2401,7 +2400,7 @@ static bool BuiltinPopcountg(Sema &S, CallExpr *TheCall) { /// an unsigned integer, and an optional second argument, which is promoted to /// an 'int'. static bool BuiltinCountZeroBitsGeneric(Sema &S, CallExpr *TheCall) { - if (checkArgCountRange(S, TheCall, 1, 2)) + if (S.checkArgCountRange(TheCall, 1, 2)) return true; ExprResult Arg0Res = S.DefaultLvalueConversion(TheCall->getArg(0)); @@ -2625,7 +2624,8 @@ Sema::CheckBuiltinFunctionCall(FunctionDecl *FDecl, unsigned BuiltinID, return ExprError(); break; case Builtin::BI__builtin_classify_type: - if (checkArgCount(*this, TheCall, 1)) return true; + if (checkArgCount(TheCall, 1)) + return true; TheCall->setType(Context.IntTy); break; case Builtin::BI__builtin_complex: @@ -2633,7 +2633,8 @@ Sema::CheckBuiltinFunctionCall(FunctionDecl *FDecl, unsigned BuiltinID, return ExprError(); break; case Builtin::BI__builtin_constant_p: { - if (checkArgCount(*this, TheCall, 1)) return true; + if (checkArgCount(TheCall, 1)) + return true; ExprResult Arg = DefaultFunctionArrayLvalueConversion(TheCall->getArg(0)); if (Arg.isInvalid()) return true; TheCall->setArg(0, Arg.get()); @@ -2822,7 +2823,7 @@ Sema::CheckBuiltinFunctionCall(FunctionDecl *FDecl, unsigned BuiltinID, return BuiltinDumpStruct(*this, TheCall); case Builtin::BI__builtin_expect_with_probability: { // We first want to ensure we are called with 3 arguments - if (checkArgCount(*this, TheCall, 3)) + if (checkArgCount(TheCall, 3)) return ExprError(); // then check probability is constant float in range [0.0, 1.0] const Expr *ProbArg = TheCall->getArg(2); @@ -2870,7 +2871,7 @@ Sema::CheckBuiltinFunctionCall(FunctionDecl *FDecl, unsigned BuiltinID, return ExprError(); break; case Builtin::BI__GetExceptionInfo: - if (checkArgCount(*this, TheCall, 1)) + if (checkArgCount(TheCall, 1)) return ExprError(); if (CheckCXXThrowOperand( @@ -2891,7 +2892,7 @@ Sema::CheckBuiltinFunctionCall(FunctionDecl *FDecl, unsigned BuiltinID, // These are all expected to be of the form // T &/&&/* f(U &/&&) // where T and U only differ in qualification. - if (checkArgCount(*this, TheCall, 1)) + if (checkArgCount(TheCall, 1)) return ExprError(); QualType Param = FDecl->getParamDecl(0)->getType(); QualType Result = FDecl->getReturnType(); @@ -3129,7 +3130,7 @@ Sema::CheckBuiltinFunctionCall(FunctionDecl *FDecl, unsigned BuiltinID, } case Builtin::BI__builtin_elementwise_copysign: { - if (checkArgCount(*this, TheCall, 2)) + if (checkArgCount(TheCall, 2)) return ExprError(); ExprResult Magnitude = UsualUnaryConversions(TheCall->getArg(0)); @@ -3806,7 +3807,7 @@ bool Sema::CheckARMBuiltinExclusiveCall(unsigned BuiltinID, CallExpr *TheCall, DeclRefExpr *DRE =cast(TheCall->getCallee()->IgnoreParenCasts()); // Ensure that we have the proper number of arguments. - if (checkArgCount(*this, TheCall, IsLdrex ? 1 : 2)) + if (checkArgCount(TheCall, IsLdrex ? 1 : 2)) return true; // Inspect the pointer argument of the atomic builtin. This should always be @@ -4145,7 +4146,7 @@ bool Sema::CheckBPFBuiltinFunctionCall(unsigned BuiltinID, BuiltinID == BPF::BI__builtin_preserve_enum_value) && "unexpected BPF builtin"); - if (checkArgCount(*this, TheCall, 2)) + if (checkArgCount(TheCall, 2)) return true; // The second argument needs to be a constant int @@ -5589,12 +5590,12 @@ bool Sema::CheckHLSLBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) { switch (BuiltinID) { case Builtin::BI__builtin_hlsl_elementwise_all: case Builtin::BI__builtin_hlsl_elementwise_any: { - if (checkArgCount(*this, TheCall, 1)) + if (checkArgCount(TheCall, 1)) return true; break; } case Builtin::BI__builtin_hlsl_elementwise_clamp: { - if (checkArgCount(*this, TheCall, 3)) + if (checkArgCount(TheCall, 3)) return true; if (CheckVectorElementCallArgs(this, TheCall)) return true; @@ -5605,7 +5606,7 @@ bool Sema::CheckHLSLBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) { break; } case Builtin::BI__builtin_hlsl_dot: { - if (checkArgCount(*this, TheCall, 2)) + if (checkArgCount(TheCall, 2)) return true; if (CheckVectorElementCallArgs(this, TheCall)) return true; @@ -5639,7 +5640,7 @@ bool Sema::CheckHLSLBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) { break; } case Builtin::BI__builtin_hlsl_lerp: { - if (checkArgCount(*this, TheCall, 3)) + if (checkArgCount(TheCall, 3)) return true; if (CheckVectorElementCallArgs(this, TheCall)) return true; @@ -5650,7 +5651,7 @@ bool Sema::CheckHLSLBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) { break; } case Builtin::BI__builtin_hlsl_mad: { - if (checkArgCount(*this, TheCall, 3)) + if (checkArgCount(TheCall, 3)) return true; if (CheckVectorElementCallArgs(this, TheCall)) return true; @@ -5753,866 +5754,6 @@ bool Sema::CheckAMDGCNBuiltinFunctionCall(unsigned BuiltinID, return false; } -bool Sema::CheckRISCVLMUL(CallExpr *TheCall, unsigned ArgNum) { - llvm::APSInt Result; - - // We can't check the value of a dependent argument. - Expr *Arg = TheCall->getArg(ArgNum); - if (Arg->isTypeDependent() || Arg->isValueDependent()) - return false; - - // Check constant-ness first. - if (BuiltinConstantArg(TheCall, ArgNum, Result)) - return true; - - int64_t Val = Result.getSExtValue(); - if ((Val >= 0 && Val <= 3) || (Val >= 5 && Val <= 7)) - return false; - - return Diag(TheCall->getBeginLoc(), diag::err_riscv_builtin_invalid_lmul) - << Arg->getSourceRange(); -} - -static bool CheckInvalidVLENandLMUL(const TargetInfo &TI, CallExpr *TheCall, - Sema &S, QualType Type, int EGW) { - assert((EGW == 128 || EGW == 256) && "EGW can only be 128 or 256 bits"); - - // LMUL * VLEN >= EGW - ASTContext::BuiltinVectorTypeInfo Info = - S.Context.getBuiltinVectorTypeInfo(Type->castAs()); - unsigned ElemSize = S.Context.getTypeSize(Info.ElementType); - unsigned MinElemCount = Info.EC.getKnownMinValue(); - - unsigned EGS = EGW / ElemSize; - // If EGS is less than or equal to the minimum number of elements, then the - // type is valid. - if (EGS <= MinElemCount) - return false; - - // Otherwise, we need vscale to be at least EGS / MinElemCont. - assert(EGS % MinElemCount == 0); - unsigned VScaleFactor = EGS / MinElemCount; - // Vscale is VLEN/RVVBitsPerBlock. - unsigned MinRequiredVLEN = VScaleFactor * llvm::RISCV::RVVBitsPerBlock; - std::string RequiredExt = "zvl" + std::to_string(MinRequiredVLEN) + "b"; - if (!TI.hasFeature(RequiredExt)) - return S.Diag(TheCall->getBeginLoc(), - diag::err_riscv_type_requires_extension) << Type << RequiredExt; - - return false; -} - -bool Sema::CheckRISCVBuiltinFunctionCall(const TargetInfo &TI, - unsigned BuiltinID, - CallExpr *TheCall) { - // vmulh.vv, vmulh.vx, vmulhu.vv, vmulhu.vx, vmulhsu.vv, vmulhsu.vx, - // vsmul.vv, vsmul.vx are not included for EEW=64 in Zve64*. - switch (BuiltinID) { - default: - break; - case RISCVVector::BI__builtin_rvv_vmulhsu_vv: - case RISCVVector::BI__builtin_rvv_vmulhsu_vx: - case RISCVVector::BI__builtin_rvv_vmulhsu_vv_tu: - case RISCVVector::BI__builtin_rvv_vmulhsu_vx_tu: - case RISCVVector::BI__builtin_rvv_vmulhsu_vv_m: - case RISCVVector::BI__builtin_rvv_vmulhsu_vx_m: - case RISCVVector::BI__builtin_rvv_vmulhsu_vv_mu: - case RISCVVector::BI__builtin_rvv_vmulhsu_vx_mu: - case RISCVVector::BI__builtin_rvv_vmulhsu_vv_tum: - case RISCVVector::BI__builtin_rvv_vmulhsu_vx_tum: - case RISCVVector::BI__builtin_rvv_vmulhsu_vv_tumu: - case RISCVVector::BI__builtin_rvv_vmulhsu_vx_tumu: - case RISCVVector::BI__builtin_rvv_vmulhu_vv: - case RISCVVector::BI__builtin_rvv_vmulhu_vx: - case RISCVVector::BI__builtin_rvv_vmulhu_vv_tu: - case RISCVVector::BI__builtin_rvv_vmulhu_vx_tu: - case RISCVVector::BI__builtin_rvv_vmulhu_vv_m: - case RISCVVector::BI__builtin_rvv_vmulhu_vx_m: - case RISCVVector::BI__builtin_rvv_vmulhu_vv_mu: - case RISCVVector::BI__builtin_rvv_vmulhu_vx_mu: - case RISCVVector::BI__builtin_rvv_vmulhu_vv_tum: - case RISCVVector::BI__builtin_rvv_vmulhu_vx_tum: - case RISCVVector::BI__builtin_rvv_vmulhu_vv_tumu: - case RISCVVector::BI__builtin_rvv_vmulhu_vx_tumu: - case RISCVVector::BI__builtin_rvv_vmulh_vv: - case RISCVVector::BI__builtin_rvv_vmulh_vx: - case RISCVVector::BI__builtin_rvv_vmulh_vv_tu: - case RISCVVector::BI__builtin_rvv_vmulh_vx_tu: - case RISCVVector::BI__builtin_rvv_vmulh_vv_m: - case RISCVVector::BI__builtin_rvv_vmulh_vx_m: - case RISCVVector::BI__builtin_rvv_vmulh_vv_mu: - case RISCVVector::BI__builtin_rvv_vmulh_vx_mu: - case RISCVVector::BI__builtin_rvv_vmulh_vv_tum: - case RISCVVector::BI__builtin_rvv_vmulh_vx_tum: - case RISCVVector::BI__builtin_rvv_vmulh_vv_tumu: - case RISCVVector::BI__builtin_rvv_vmulh_vx_tumu: - case RISCVVector::BI__builtin_rvv_vsmul_vv: - case RISCVVector::BI__builtin_rvv_vsmul_vx: - case RISCVVector::BI__builtin_rvv_vsmul_vv_tu: - case RISCVVector::BI__builtin_rvv_vsmul_vx_tu: - case RISCVVector::BI__builtin_rvv_vsmul_vv_m: - case RISCVVector::BI__builtin_rvv_vsmul_vx_m: - case RISCVVector::BI__builtin_rvv_vsmul_vv_mu: - case RISCVVector::BI__builtin_rvv_vsmul_vx_mu: - case RISCVVector::BI__builtin_rvv_vsmul_vv_tum: - case RISCVVector::BI__builtin_rvv_vsmul_vx_tum: - case RISCVVector::BI__builtin_rvv_vsmul_vv_tumu: - case RISCVVector::BI__builtin_rvv_vsmul_vx_tumu: { - ASTContext::BuiltinVectorTypeInfo Info = Context.getBuiltinVectorTypeInfo( - TheCall->getType()->castAs()); - - if (Context.getTypeSize(Info.ElementType) == 64 && !TI.hasFeature("v")) - return Diag(TheCall->getBeginLoc(), - diag::err_riscv_builtin_requires_extension) - << /* IsExtension */ true << TheCall->getSourceRange() << "v"; - - break; - } - } - - switch (BuiltinID) { - case RISCVVector::BI__builtin_rvv_vsetvli: - return BuiltinConstantArgRange(TheCall, 1, 0, 3) || - CheckRISCVLMUL(TheCall, 2); - case RISCVVector::BI__builtin_rvv_vsetvlimax: - return BuiltinConstantArgRange(TheCall, 0, 0, 3) || - CheckRISCVLMUL(TheCall, 1); - case RISCVVector::BI__builtin_rvv_vget_v: { - ASTContext::BuiltinVectorTypeInfo ResVecInfo = - Context.getBuiltinVectorTypeInfo(cast( - TheCall->getType().getCanonicalType().getTypePtr())); - ASTContext::BuiltinVectorTypeInfo VecInfo = - Context.getBuiltinVectorTypeInfo(cast( - TheCall->getArg(0)->getType().getCanonicalType().getTypePtr())); - unsigned MaxIndex; - if (VecInfo.NumVectors != 1) // vget for tuple type - MaxIndex = VecInfo.NumVectors; - else // vget for non-tuple type - MaxIndex = (VecInfo.EC.getKnownMinValue() * VecInfo.NumVectors) / - (ResVecInfo.EC.getKnownMinValue() * ResVecInfo.NumVectors); - return BuiltinConstantArgRange(TheCall, 1, 0, MaxIndex - 1); - } - case RISCVVector::BI__builtin_rvv_vset_v: { - ASTContext::BuiltinVectorTypeInfo ResVecInfo = - Context.getBuiltinVectorTypeInfo(cast( - TheCall->getType().getCanonicalType().getTypePtr())); - ASTContext::BuiltinVectorTypeInfo VecInfo = - Context.getBuiltinVectorTypeInfo(cast( - TheCall->getArg(2)->getType().getCanonicalType().getTypePtr())); - unsigned MaxIndex; - if (ResVecInfo.NumVectors != 1) // vset for tuple type - MaxIndex = ResVecInfo.NumVectors; - else // vset fo non-tuple type - MaxIndex = (ResVecInfo.EC.getKnownMinValue() * ResVecInfo.NumVectors) / - (VecInfo.EC.getKnownMinValue() * VecInfo.NumVectors); - return BuiltinConstantArgRange(TheCall, 1, 0, MaxIndex - 1); - } - // Vector Crypto - case RISCVVector::BI__builtin_rvv_vaeskf1_vi_tu: - case RISCVVector::BI__builtin_rvv_vaeskf2_vi_tu: - case RISCVVector::BI__builtin_rvv_vaeskf2_vi: - case RISCVVector::BI__builtin_rvv_vsm4k_vi_tu: { - QualType Op1Type = TheCall->getArg(0)->getType(); - QualType Op2Type = TheCall->getArg(1)->getType(); - return CheckInvalidVLENandLMUL(TI, TheCall, *this, Op1Type, 128) || - CheckInvalidVLENandLMUL(TI, TheCall, *this, Op2Type, 128) || - BuiltinConstantArgRange(TheCall, 2, 0, 31); - } - case RISCVVector::BI__builtin_rvv_vsm3c_vi_tu: - case RISCVVector::BI__builtin_rvv_vsm3c_vi: { - QualType Op1Type = TheCall->getArg(0)->getType(); - return CheckInvalidVLENandLMUL(TI, TheCall, *this, Op1Type, 256) || - BuiltinConstantArgRange(TheCall, 2, 0, 31); - } - case RISCVVector::BI__builtin_rvv_vaeskf1_vi: - case RISCVVector::BI__builtin_rvv_vsm4k_vi: { - QualType Op1Type = TheCall->getArg(0)->getType(); - return CheckInvalidVLENandLMUL(TI, TheCall, *this, Op1Type, 128) || - BuiltinConstantArgRange(TheCall, 1, 0, 31); - } - case RISCVVector::BI__builtin_rvv_vaesdf_vv: - case RISCVVector::BI__builtin_rvv_vaesdf_vs: - case RISCVVector::BI__builtin_rvv_vaesdm_vv: - case RISCVVector::BI__builtin_rvv_vaesdm_vs: - case RISCVVector::BI__builtin_rvv_vaesef_vv: - case RISCVVector::BI__builtin_rvv_vaesef_vs: - case RISCVVector::BI__builtin_rvv_vaesem_vv: - case RISCVVector::BI__builtin_rvv_vaesem_vs: - case RISCVVector::BI__builtin_rvv_vaesz_vs: - case RISCVVector::BI__builtin_rvv_vsm4r_vv: - case RISCVVector::BI__builtin_rvv_vsm4r_vs: - case RISCVVector::BI__builtin_rvv_vaesdf_vv_tu: - case RISCVVector::BI__builtin_rvv_vaesdf_vs_tu: - case RISCVVector::BI__builtin_rvv_vaesdm_vv_tu: - case RISCVVector::BI__builtin_rvv_vaesdm_vs_tu: - case RISCVVector::BI__builtin_rvv_vaesef_vv_tu: - case RISCVVector::BI__builtin_rvv_vaesef_vs_tu: - case RISCVVector::BI__builtin_rvv_vaesem_vv_tu: - case RISCVVector::BI__builtin_rvv_vaesem_vs_tu: - case RISCVVector::BI__builtin_rvv_vaesz_vs_tu: - case RISCVVector::BI__builtin_rvv_vsm4r_vv_tu: - case RISCVVector::BI__builtin_rvv_vsm4r_vs_tu: { - QualType Op1Type = TheCall->getArg(0)->getType(); - QualType Op2Type = TheCall->getArg(1)->getType(); - return CheckInvalidVLENandLMUL(TI, TheCall, *this, Op1Type, 128) || - CheckInvalidVLENandLMUL(TI, TheCall, *this, Op2Type, 128); - } - case RISCVVector::BI__builtin_rvv_vsha2ch_vv: - case RISCVVector::BI__builtin_rvv_vsha2cl_vv: - case RISCVVector::BI__builtin_rvv_vsha2ms_vv: - case RISCVVector::BI__builtin_rvv_vsha2ch_vv_tu: - case RISCVVector::BI__builtin_rvv_vsha2cl_vv_tu: - case RISCVVector::BI__builtin_rvv_vsha2ms_vv_tu: { - QualType Op1Type = TheCall->getArg(0)->getType(); - QualType Op2Type = TheCall->getArg(1)->getType(); - QualType Op3Type = TheCall->getArg(2)->getType(); - ASTContext::BuiltinVectorTypeInfo Info = - Context.getBuiltinVectorTypeInfo(Op1Type->castAs()); - uint64_t ElemSize = Context.getTypeSize(Info.ElementType); - if (ElemSize == 64 && !TI.hasFeature("zvknhb")) - return Diag(TheCall->getBeginLoc(), - diag::err_riscv_builtin_requires_extension) - << /* IsExtension */ true << TheCall->getSourceRange() << "zvknb"; - - return CheckInvalidVLENandLMUL(TI, TheCall, *this, Op1Type, ElemSize * 4) || - CheckInvalidVLENandLMUL(TI, TheCall, *this, Op2Type, ElemSize * 4) || - CheckInvalidVLENandLMUL(TI, TheCall, *this, Op3Type, ElemSize * 4); - } - - case RISCVVector::BI__builtin_rvv_sf_vc_i_se: - // bit_27_26, bit_24_20, bit_11_7, simm5, sew, log2lmul - return BuiltinConstantArgRange(TheCall, 0, 0, 3) || - BuiltinConstantArgRange(TheCall, 1, 0, 31) || - BuiltinConstantArgRange(TheCall, 2, 0, 31) || - BuiltinConstantArgRange(TheCall, 3, -16, 15) || - CheckRISCVLMUL(TheCall, 5); - case RISCVVector::BI__builtin_rvv_sf_vc_iv_se: - // bit_27_26, bit_11_7, vs2, simm5 - return BuiltinConstantArgRange(TheCall, 0, 0, 3) || - BuiltinConstantArgRange(TheCall, 1, 0, 31) || - BuiltinConstantArgRange(TheCall, 3, -16, 15); - case RISCVVector::BI__builtin_rvv_sf_vc_v_i: - case RISCVVector::BI__builtin_rvv_sf_vc_v_i_se: - // bit_27_26, bit_24_20, simm5 - return BuiltinConstantArgRange(TheCall, 0, 0, 3) || - BuiltinConstantArgRange(TheCall, 1, 0, 31) || - BuiltinConstantArgRange(TheCall, 2, -16, 15); - case RISCVVector::BI__builtin_rvv_sf_vc_v_iv: - case RISCVVector::BI__builtin_rvv_sf_vc_v_iv_se: - // bit_27_26, vs2, simm5 - return BuiltinConstantArgRange(TheCall, 0, 0, 3) || - BuiltinConstantArgRange(TheCall, 2, -16, 15); - case RISCVVector::BI__builtin_rvv_sf_vc_ivv_se: - case RISCVVector::BI__builtin_rvv_sf_vc_ivw_se: - case RISCVVector::BI__builtin_rvv_sf_vc_v_ivv: - case RISCVVector::BI__builtin_rvv_sf_vc_v_ivw: - case RISCVVector::BI__builtin_rvv_sf_vc_v_ivv_se: - case RISCVVector::BI__builtin_rvv_sf_vc_v_ivw_se: - // bit_27_26, vd, vs2, simm5 - return BuiltinConstantArgRange(TheCall, 0, 0, 3) || - BuiltinConstantArgRange(TheCall, 3, -16, 15); - case RISCVVector::BI__builtin_rvv_sf_vc_x_se: - // bit_27_26, bit_24_20, bit_11_7, xs1, sew, log2lmul - return BuiltinConstantArgRange(TheCall, 0, 0, 3) || - BuiltinConstantArgRange(TheCall, 1, 0, 31) || - BuiltinConstantArgRange(TheCall, 2, 0, 31) || - CheckRISCVLMUL(TheCall, 5); - case RISCVVector::BI__builtin_rvv_sf_vc_xv_se: - case RISCVVector::BI__builtin_rvv_sf_vc_vv_se: - // bit_27_26, bit_11_7, vs2, xs1/vs1 - case RISCVVector::BI__builtin_rvv_sf_vc_v_x: - case RISCVVector::BI__builtin_rvv_sf_vc_v_x_se: - // bit_27_26, bit_24-20, xs1 - return BuiltinConstantArgRange(TheCall, 0, 0, 3) || - BuiltinConstantArgRange(TheCall, 1, 0, 31); - case RISCVVector::BI__builtin_rvv_sf_vc_vvv_se: - case RISCVVector::BI__builtin_rvv_sf_vc_xvv_se: - case RISCVVector::BI__builtin_rvv_sf_vc_vvw_se: - case RISCVVector::BI__builtin_rvv_sf_vc_xvw_se: - // bit_27_26, vd, vs2, xs1 - case RISCVVector::BI__builtin_rvv_sf_vc_v_xv: - case RISCVVector::BI__builtin_rvv_sf_vc_v_vv: - case RISCVVector::BI__builtin_rvv_sf_vc_v_xv_se: - case RISCVVector::BI__builtin_rvv_sf_vc_v_vv_se: - // bit_27_26, vs2, xs1/vs1 - case RISCVVector::BI__builtin_rvv_sf_vc_v_xvv: - case RISCVVector::BI__builtin_rvv_sf_vc_v_vvv: - case RISCVVector::BI__builtin_rvv_sf_vc_v_xvw: - case RISCVVector::BI__builtin_rvv_sf_vc_v_vvw: - case RISCVVector::BI__builtin_rvv_sf_vc_v_xvv_se: - case RISCVVector::BI__builtin_rvv_sf_vc_v_vvv_se: - case RISCVVector::BI__builtin_rvv_sf_vc_v_xvw_se: - case RISCVVector::BI__builtin_rvv_sf_vc_v_vvw_se: - // bit_27_26, vd, vs2, xs1/vs1 - return BuiltinConstantArgRange(TheCall, 0, 0, 3); - case RISCVVector::BI__builtin_rvv_sf_vc_fv_se: - // bit_26, bit_11_7, vs2, fs1 - return BuiltinConstantArgRange(TheCall, 0, 0, 1) || - BuiltinConstantArgRange(TheCall, 1, 0, 31); - case RISCVVector::BI__builtin_rvv_sf_vc_fvv_se: - case RISCVVector::BI__builtin_rvv_sf_vc_fvw_se: - case RISCVVector::BI__builtin_rvv_sf_vc_v_fvv: - case RISCVVector::BI__builtin_rvv_sf_vc_v_fvw: - case RISCVVector::BI__builtin_rvv_sf_vc_v_fvv_se: - case RISCVVector::BI__builtin_rvv_sf_vc_v_fvw_se: - // bit_26, vd, vs2, fs1 - case RISCVVector::BI__builtin_rvv_sf_vc_v_fv: - case RISCVVector::BI__builtin_rvv_sf_vc_v_fv_se: - // bit_26, vs2, fs1 - return BuiltinConstantArgRange(TheCall, 0, 0, 1); - // Check if byteselect is in [0, 3] - case RISCV::BI__builtin_riscv_aes32dsi: - case RISCV::BI__builtin_riscv_aes32dsmi: - case RISCV::BI__builtin_riscv_aes32esi: - case RISCV::BI__builtin_riscv_aes32esmi: - case RISCV::BI__builtin_riscv_sm4ks: - case RISCV::BI__builtin_riscv_sm4ed: - return BuiltinConstantArgRange(TheCall, 2, 0, 3); - // Check if rnum is in [0, 10] - case RISCV::BI__builtin_riscv_aes64ks1i: - return BuiltinConstantArgRange(TheCall, 1, 0, 10); - // Check if value range for vxrm is in [0, 3] - case RISCVVector::BI__builtin_rvv_vaaddu_vv: - case RISCVVector::BI__builtin_rvv_vaaddu_vx: - case RISCVVector::BI__builtin_rvv_vaadd_vv: - case RISCVVector::BI__builtin_rvv_vaadd_vx: - case RISCVVector::BI__builtin_rvv_vasubu_vv: - case RISCVVector::BI__builtin_rvv_vasubu_vx: - case RISCVVector::BI__builtin_rvv_vasub_vv: - case RISCVVector::BI__builtin_rvv_vasub_vx: - case RISCVVector::BI__builtin_rvv_vsmul_vv: - case RISCVVector::BI__builtin_rvv_vsmul_vx: - case RISCVVector::BI__builtin_rvv_vssra_vv: - case RISCVVector::BI__builtin_rvv_vssra_vx: - case RISCVVector::BI__builtin_rvv_vssrl_vv: - case RISCVVector::BI__builtin_rvv_vssrl_vx: - case RISCVVector::BI__builtin_rvv_vnclip_wv: - case RISCVVector::BI__builtin_rvv_vnclip_wx: - case RISCVVector::BI__builtin_rvv_vnclipu_wv: - case RISCVVector::BI__builtin_rvv_vnclipu_wx: - return BuiltinConstantArgRange(TheCall, 2, 0, 3); - case RISCVVector::BI__builtin_rvv_vaaddu_vv_tu: - case RISCVVector::BI__builtin_rvv_vaaddu_vx_tu: - case RISCVVector::BI__builtin_rvv_vaadd_vv_tu: - case RISCVVector::BI__builtin_rvv_vaadd_vx_tu: - case RISCVVector::BI__builtin_rvv_vasubu_vv_tu: - case RISCVVector::BI__builtin_rvv_vasubu_vx_tu: - case RISCVVector::BI__builtin_rvv_vasub_vv_tu: - case RISCVVector::BI__builtin_rvv_vasub_vx_tu: - case RISCVVector::BI__builtin_rvv_vsmul_vv_tu: - case RISCVVector::BI__builtin_rvv_vsmul_vx_tu: - case RISCVVector::BI__builtin_rvv_vssra_vv_tu: - case RISCVVector::BI__builtin_rvv_vssra_vx_tu: - case RISCVVector::BI__builtin_rvv_vssrl_vv_tu: - case RISCVVector::BI__builtin_rvv_vssrl_vx_tu: - case RISCVVector::BI__builtin_rvv_vnclip_wv_tu: - case RISCVVector::BI__builtin_rvv_vnclip_wx_tu: - case RISCVVector::BI__builtin_rvv_vnclipu_wv_tu: - case RISCVVector::BI__builtin_rvv_vnclipu_wx_tu: - case RISCVVector::BI__builtin_rvv_vaaddu_vv_m: - case RISCVVector::BI__builtin_rvv_vaaddu_vx_m: - case RISCVVector::BI__builtin_rvv_vaadd_vv_m: - case RISCVVector::BI__builtin_rvv_vaadd_vx_m: - case RISCVVector::BI__builtin_rvv_vasubu_vv_m: - case RISCVVector::BI__builtin_rvv_vasubu_vx_m: - case RISCVVector::BI__builtin_rvv_vasub_vv_m: - case RISCVVector::BI__builtin_rvv_vasub_vx_m: - case RISCVVector::BI__builtin_rvv_vsmul_vv_m: - case RISCVVector::BI__builtin_rvv_vsmul_vx_m: - case RISCVVector::BI__builtin_rvv_vssra_vv_m: - case RISCVVector::BI__builtin_rvv_vssra_vx_m: - case RISCVVector::BI__builtin_rvv_vssrl_vv_m: - case RISCVVector::BI__builtin_rvv_vssrl_vx_m: - case RISCVVector::BI__builtin_rvv_vnclip_wv_m: - case RISCVVector::BI__builtin_rvv_vnclip_wx_m: - case RISCVVector::BI__builtin_rvv_vnclipu_wv_m: - case RISCVVector::BI__builtin_rvv_vnclipu_wx_m: - return BuiltinConstantArgRange(TheCall, 3, 0, 3); - case RISCVVector::BI__builtin_rvv_vaaddu_vv_tum: - case RISCVVector::BI__builtin_rvv_vaaddu_vv_tumu: - case RISCVVector::BI__builtin_rvv_vaaddu_vv_mu: - case RISCVVector::BI__builtin_rvv_vaaddu_vx_tum: - case RISCVVector::BI__builtin_rvv_vaaddu_vx_tumu: - case RISCVVector::BI__builtin_rvv_vaaddu_vx_mu: - case RISCVVector::BI__builtin_rvv_vaadd_vv_tum: - case RISCVVector::BI__builtin_rvv_vaadd_vv_tumu: - case RISCVVector::BI__builtin_rvv_vaadd_vv_mu: - case RISCVVector::BI__builtin_rvv_vaadd_vx_tum: - case RISCVVector::BI__builtin_rvv_vaadd_vx_tumu: - case RISCVVector::BI__builtin_rvv_vaadd_vx_mu: - case RISCVVector::BI__builtin_rvv_vasubu_vv_tum: - case RISCVVector::BI__builtin_rvv_vasubu_vv_tumu: - case RISCVVector::BI__builtin_rvv_vasubu_vv_mu: - case RISCVVector::BI__builtin_rvv_vasubu_vx_tum: - case RISCVVector::BI__builtin_rvv_vasubu_vx_tumu: - case RISCVVector::BI__builtin_rvv_vasubu_vx_mu: - case RISCVVector::BI__builtin_rvv_vasub_vv_tum: - case RISCVVector::BI__builtin_rvv_vasub_vv_tumu: - case RISCVVector::BI__builtin_rvv_vasub_vv_mu: - case RISCVVector::BI__builtin_rvv_vasub_vx_tum: - case RISCVVector::BI__builtin_rvv_vasub_vx_tumu: - case RISCVVector::BI__builtin_rvv_vasub_vx_mu: - case RISCVVector::BI__builtin_rvv_vsmul_vv_mu: - case RISCVVector::BI__builtin_rvv_vsmul_vx_mu: - case RISCVVector::BI__builtin_rvv_vssra_vv_mu: - case RISCVVector::BI__builtin_rvv_vssra_vx_mu: - case RISCVVector::BI__builtin_rvv_vssrl_vv_mu: - case RISCVVector::BI__builtin_rvv_vssrl_vx_mu: - case RISCVVector::BI__builtin_rvv_vnclip_wv_mu: - case RISCVVector::BI__builtin_rvv_vnclip_wx_mu: - case RISCVVector::BI__builtin_rvv_vnclipu_wv_mu: - case RISCVVector::BI__builtin_rvv_vnclipu_wx_mu: - case RISCVVector::BI__builtin_rvv_vsmul_vv_tum: - case RISCVVector::BI__builtin_rvv_vsmul_vx_tum: - case RISCVVector::BI__builtin_rvv_vssra_vv_tum: - case RISCVVector::BI__builtin_rvv_vssra_vx_tum: - case RISCVVector::BI__builtin_rvv_vssrl_vv_tum: - case RISCVVector::BI__builtin_rvv_vssrl_vx_tum: - case RISCVVector::BI__builtin_rvv_vnclip_wv_tum: - case RISCVVector::BI__builtin_rvv_vnclip_wx_tum: - case RISCVVector::BI__builtin_rvv_vnclipu_wv_tum: - case RISCVVector::BI__builtin_rvv_vnclipu_wx_tum: - case RISCVVector::BI__builtin_rvv_vsmul_vv_tumu: - case RISCVVector::BI__builtin_rvv_vsmul_vx_tumu: - case RISCVVector::BI__builtin_rvv_vssra_vv_tumu: - case RISCVVector::BI__builtin_rvv_vssra_vx_tumu: - case RISCVVector::BI__builtin_rvv_vssrl_vv_tumu: - case RISCVVector::BI__builtin_rvv_vssrl_vx_tumu: - case RISCVVector::BI__builtin_rvv_vnclip_wv_tumu: - case RISCVVector::BI__builtin_rvv_vnclip_wx_tumu: - case RISCVVector::BI__builtin_rvv_vnclipu_wv_tumu: - case RISCVVector::BI__builtin_rvv_vnclipu_wx_tumu: - return BuiltinConstantArgRange(TheCall, 4, 0, 3); - case RISCVVector::BI__builtin_rvv_vfsqrt_v_rm: - case RISCVVector::BI__builtin_rvv_vfrec7_v_rm: - case RISCVVector::BI__builtin_rvv_vfcvt_x_f_v_rm: - case RISCVVector::BI__builtin_rvv_vfcvt_xu_f_v_rm: - case RISCVVector::BI__builtin_rvv_vfcvt_f_x_v_rm: - case RISCVVector::BI__builtin_rvv_vfcvt_f_xu_v_rm: - case RISCVVector::BI__builtin_rvv_vfwcvt_x_f_v_rm: - case RISCVVector::BI__builtin_rvv_vfwcvt_xu_f_v_rm: - case RISCVVector::BI__builtin_rvv_vfncvt_x_f_w_rm: - case RISCVVector::BI__builtin_rvv_vfncvt_xu_f_w_rm: - case RISCVVector::BI__builtin_rvv_vfncvt_f_x_w_rm: - case RISCVVector::BI__builtin_rvv_vfncvt_f_xu_w_rm: - case RISCVVector::BI__builtin_rvv_vfncvt_f_f_w_rm: - return BuiltinConstantArgRange(TheCall, 1, 0, 4); - case RISCVVector::BI__builtin_rvv_vfadd_vv_rm: - case RISCVVector::BI__builtin_rvv_vfadd_vf_rm: - case RISCVVector::BI__builtin_rvv_vfsub_vv_rm: - case RISCVVector::BI__builtin_rvv_vfsub_vf_rm: - case RISCVVector::BI__builtin_rvv_vfrsub_vf_rm: - case RISCVVector::BI__builtin_rvv_vfwadd_vv_rm: - case RISCVVector::BI__builtin_rvv_vfwadd_vf_rm: - case RISCVVector::BI__builtin_rvv_vfwsub_vv_rm: - case RISCVVector::BI__builtin_rvv_vfwsub_vf_rm: - case RISCVVector::BI__builtin_rvv_vfwadd_wv_rm: - case RISCVVector::BI__builtin_rvv_vfwadd_wf_rm: - case RISCVVector::BI__builtin_rvv_vfwsub_wv_rm: - case RISCVVector::BI__builtin_rvv_vfwsub_wf_rm: - case RISCVVector::BI__builtin_rvv_vfmul_vv_rm: - case RISCVVector::BI__builtin_rvv_vfmul_vf_rm: - case RISCVVector::BI__builtin_rvv_vfdiv_vv_rm: - case RISCVVector::BI__builtin_rvv_vfdiv_vf_rm: - case RISCVVector::BI__builtin_rvv_vfrdiv_vf_rm: - case RISCVVector::BI__builtin_rvv_vfwmul_vv_rm: - case RISCVVector::BI__builtin_rvv_vfwmul_vf_rm: - case RISCVVector::BI__builtin_rvv_vfredosum_vs_rm: - case RISCVVector::BI__builtin_rvv_vfredusum_vs_rm: - case RISCVVector::BI__builtin_rvv_vfwredosum_vs_rm: - case RISCVVector::BI__builtin_rvv_vfwredusum_vs_rm: - case RISCVVector::BI__builtin_rvv_vfsqrt_v_rm_tu: - case RISCVVector::BI__builtin_rvv_vfrec7_v_rm_tu: - case RISCVVector::BI__builtin_rvv_vfcvt_x_f_v_rm_tu: - case RISCVVector::BI__builtin_rvv_vfcvt_xu_f_v_rm_tu: - case RISCVVector::BI__builtin_rvv_vfcvt_f_x_v_rm_tu: - case RISCVVector::BI__builtin_rvv_vfcvt_f_xu_v_rm_tu: - case RISCVVector::BI__builtin_rvv_vfwcvt_x_f_v_rm_tu: - case RISCVVector::BI__builtin_rvv_vfwcvt_xu_f_v_rm_tu: - case RISCVVector::BI__builtin_rvv_vfncvt_x_f_w_rm_tu: - case RISCVVector::BI__builtin_rvv_vfncvt_xu_f_w_rm_tu: - case RISCVVector::BI__builtin_rvv_vfncvt_f_x_w_rm_tu: - case RISCVVector::BI__builtin_rvv_vfncvt_f_xu_w_rm_tu: - case RISCVVector::BI__builtin_rvv_vfncvt_f_f_w_rm_tu: - case RISCVVector::BI__builtin_rvv_vfsqrt_v_rm_m: - case RISCVVector::BI__builtin_rvv_vfrec7_v_rm_m: - case RISCVVector::BI__builtin_rvv_vfcvt_x_f_v_rm_m: - case RISCVVector::BI__builtin_rvv_vfcvt_xu_f_v_rm_m: - case RISCVVector::BI__builtin_rvv_vfcvt_f_x_v_rm_m: - case RISCVVector::BI__builtin_rvv_vfcvt_f_xu_v_rm_m: - case RISCVVector::BI__builtin_rvv_vfwcvt_x_f_v_rm_m: - case RISCVVector::BI__builtin_rvv_vfwcvt_xu_f_v_rm_m: - case RISCVVector::BI__builtin_rvv_vfncvt_x_f_w_rm_m: - case RISCVVector::BI__builtin_rvv_vfncvt_xu_f_w_rm_m: - case RISCVVector::BI__builtin_rvv_vfncvt_f_x_w_rm_m: - case RISCVVector::BI__builtin_rvv_vfncvt_f_xu_w_rm_m: - case RISCVVector::BI__builtin_rvv_vfncvt_f_f_w_rm_m: - return BuiltinConstantArgRange(TheCall, 2, 0, 4); - case RISCVVector::BI__builtin_rvv_vfadd_vv_rm_tu: - case RISCVVector::BI__builtin_rvv_vfadd_vf_rm_tu: - case RISCVVector::BI__builtin_rvv_vfsub_vv_rm_tu: - case RISCVVector::BI__builtin_rvv_vfsub_vf_rm_tu: - case RISCVVector::BI__builtin_rvv_vfrsub_vf_rm_tu: - case RISCVVector::BI__builtin_rvv_vfwadd_vv_rm_tu: - case RISCVVector::BI__builtin_rvv_vfwadd_vf_rm_tu: - case RISCVVector::BI__builtin_rvv_vfwsub_vv_rm_tu: - case RISCVVector::BI__builtin_rvv_vfwsub_vf_rm_tu: - case RISCVVector::BI__builtin_rvv_vfwadd_wv_rm_tu: - case RISCVVector::BI__builtin_rvv_vfwadd_wf_rm_tu: - case RISCVVector::BI__builtin_rvv_vfwsub_wv_rm_tu: - case RISCVVector::BI__builtin_rvv_vfwsub_wf_rm_tu: - case RISCVVector::BI__builtin_rvv_vfmul_vv_rm_tu: - case RISCVVector::BI__builtin_rvv_vfmul_vf_rm_tu: - case RISCVVector::BI__builtin_rvv_vfdiv_vv_rm_tu: - case RISCVVector::BI__builtin_rvv_vfdiv_vf_rm_tu: - case RISCVVector::BI__builtin_rvv_vfrdiv_vf_rm_tu: - case RISCVVector::BI__builtin_rvv_vfwmul_vv_rm_tu: - case RISCVVector::BI__builtin_rvv_vfwmul_vf_rm_tu: - case RISCVVector::BI__builtin_rvv_vfredosum_vs_rm_tu: - case RISCVVector::BI__builtin_rvv_vfredusum_vs_rm_tu: - case RISCVVector::BI__builtin_rvv_vfwredosum_vs_rm_tu: - case RISCVVector::BI__builtin_rvv_vfwredusum_vs_rm_tu: - case RISCVVector::BI__builtin_rvv_vfmacc_vv_rm: - case RISCVVector::BI__builtin_rvv_vfmacc_vf_rm: - case RISCVVector::BI__builtin_rvv_vfnmacc_vv_rm: - case RISCVVector::BI__builtin_rvv_vfnmacc_vf_rm: - case RISCVVector::BI__builtin_rvv_vfmsac_vv_rm: - case RISCVVector::BI__builtin_rvv_vfmsac_vf_rm: - case RISCVVector::BI__builtin_rvv_vfnmsac_vv_rm: - case RISCVVector::BI__builtin_rvv_vfnmsac_vf_rm: - case RISCVVector::BI__builtin_rvv_vfmadd_vv_rm: - case RISCVVector::BI__builtin_rvv_vfmadd_vf_rm: - case RISCVVector::BI__builtin_rvv_vfnmadd_vv_rm: - case RISCVVector::BI__builtin_rvv_vfnmadd_vf_rm: - case RISCVVector::BI__builtin_rvv_vfmsub_vv_rm: - case RISCVVector::BI__builtin_rvv_vfmsub_vf_rm: - case RISCVVector::BI__builtin_rvv_vfnmsub_vv_rm: - case RISCVVector::BI__builtin_rvv_vfnmsub_vf_rm: - case RISCVVector::BI__builtin_rvv_vfwmacc_vv_rm: - case RISCVVector::BI__builtin_rvv_vfwmacc_vf_rm: - case RISCVVector::BI__builtin_rvv_vfwnmacc_vv_rm: - case RISCVVector::BI__builtin_rvv_vfwnmacc_vf_rm: - case RISCVVector::BI__builtin_rvv_vfwmsac_vv_rm: - case RISCVVector::BI__builtin_rvv_vfwmsac_vf_rm: - case RISCVVector::BI__builtin_rvv_vfwnmsac_vv_rm: - case RISCVVector::BI__builtin_rvv_vfwnmsac_vf_rm: - case RISCVVector::BI__builtin_rvv_vfmacc_vv_rm_tu: - case RISCVVector::BI__builtin_rvv_vfmacc_vf_rm_tu: - case RISCVVector::BI__builtin_rvv_vfnmacc_vv_rm_tu: - case RISCVVector::BI__builtin_rvv_vfnmacc_vf_rm_tu: - case RISCVVector::BI__builtin_rvv_vfmsac_vv_rm_tu: - case RISCVVector::BI__builtin_rvv_vfmsac_vf_rm_tu: - case RISCVVector::BI__builtin_rvv_vfnmsac_vv_rm_tu: - case RISCVVector::BI__builtin_rvv_vfnmsac_vf_rm_tu: - case RISCVVector::BI__builtin_rvv_vfmadd_vv_rm_tu: - case RISCVVector::BI__builtin_rvv_vfmadd_vf_rm_tu: - case RISCVVector::BI__builtin_rvv_vfnmadd_vv_rm_tu: - case RISCVVector::BI__builtin_rvv_vfnmadd_vf_rm_tu: - case RISCVVector::BI__builtin_rvv_vfmsub_vv_rm_tu: - case RISCVVector::BI__builtin_rvv_vfmsub_vf_rm_tu: - case RISCVVector::BI__builtin_rvv_vfnmsub_vv_rm_tu: - case RISCVVector::BI__builtin_rvv_vfnmsub_vf_rm_tu: - case RISCVVector::BI__builtin_rvv_vfwmacc_vv_rm_tu: - case RISCVVector::BI__builtin_rvv_vfwmacc_vf_rm_tu: - case RISCVVector::BI__builtin_rvv_vfwnmacc_vv_rm_tu: - case RISCVVector::BI__builtin_rvv_vfwnmacc_vf_rm_tu: - case RISCVVector::BI__builtin_rvv_vfwmsac_vv_rm_tu: - case RISCVVector::BI__builtin_rvv_vfwmsac_vf_rm_tu: - case RISCVVector::BI__builtin_rvv_vfwnmsac_vv_rm_tu: - case RISCVVector::BI__builtin_rvv_vfwnmsac_vf_rm_tu: - case RISCVVector::BI__builtin_rvv_vfadd_vv_rm_m: - case RISCVVector::BI__builtin_rvv_vfadd_vf_rm_m: - case RISCVVector::BI__builtin_rvv_vfsub_vv_rm_m: - case RISCVVector::BI__builtin_rvv_vfsub_vf_rm_m: - case RISCVVector::BI__builtin_rvv_vfrsub_vf_rm_m: - case RISCVVector::BI__builtin_rvv_vfwadd_vv_rm_m: - case RISCVVector::BI__builtin_rvv_vfwadd_vf_rm_m: - case RISCVVector::BI__builtin_rvv_vfwsub_vv_rm_m: - case RISCVVector::BI__builtin_rvv_vfwsub_vf_rm_m: - case RISCVVector::BI__builtin_rvv_vfwadd_wv_rm_m: - case RISCVVector::BI__builtin_rvv_vfwadd_wf_rm_m: - case RISCVVector::BI__builtin_rvv_vfwsub_wv_rm_m: - case RISCVVector::BI__builtin_rvv_vfwsub_wf_rm_m: - case RISCVVector::BI__builtin_rvv_vfmul_vv_rm_m: - case RISCVVector::BI__builtin_rvv_vfmul_vf_rm_m: - case RISCVVector::BI__builtin_rvv_vfdiv_vv_rm_m: - case RISCVVector::BI__builtin_rvv_vfdiv_vf_rm_m: - case RISCVVector::BI__builtin_rvv_vfrdiv_vf_rm_m: - case RISCVVector::BI__builtin_rvv_vfwmul_vv_rm_m: - case RISCVVector::BI__builtin_rvv_vfwmul_vf_rm_m: - case RISCVVector::BI__builtin_rvv_vfredosum_vs_rm_m: - case RISCVVector::BI__builtin_rvv_vfredusum_vs_rm_m: - case RISCVVector::BI__builtin_rvv_vfwredosum_vs_rm_m: - case RISCVVector::BI__builtin_rvv_vfwredusum_vs_rm_m: - case RISCVVector::BI__builtin_rvv_vfsqrt_v_rm_tum: - case RISCVVector::BI__builtin_rvv_vfrec7_v_rm_tum: - case RISCVVector::BI__builtin_rvv_vfcvt_x_f_v_rm_tum: - case RISCVVector::BI__builtin_rvv_vfcvt_xu_f_v_rm_tum: - case RISCVVector::BI__builtin_rvv_vfcvt_f_x_v_rm_tum: - case RISCVVector::BI__builtin_rvv_vfcvt_f_xu_v_rm_tum: - case RISCVVector::BI__builtin_rvv_vfwcvt_x_f_v_rm_tum: - case RISCVVector::BI__builtin_rvv_vfwcvt_xu_f_v_rm_tum: - case RISCVVector::BI__builtin_rvv_vfncvt_x_f_w_rm_tum: - case RISCVVector::BI__builtin_rvv_vfncvt_xu_f_w_rm_tum: - case RISCVVector::BI__builtin_rvv_vfncvt_f_x_w_rm_tum: - case RISCVVector::BI__builtin_rvv_vfncvt_f_xu_w_rm_tum: - case RISCVVector::BI__builtin_rvv_vfncvt_f_f_w_rm_tum: - case RISCVVector::BI__builtin_rvv_vfsqrt_v_rm_tumu: - case RISCVVector::BI__builtin_rvv_vfrec7_v_rm_tumu: - case RISCVVector::BI__builtin_rvv_vfcvt_x_f_v_rm_tumu: - case RISCVVector::BI__builtin_rvv_vfcvt_xu_f_v_rm_tumu: - case RISCVVector::BI__builtin_rvv_vfcvt_f_x_v_rm_tumu: - case RISCVVector::BI__builtin_rvv_vfcvt_f_xu_v_rm_tumu: - case RISCVVector::BI__builtin_rvv_vfwcvt_x_f_v_rm_tumu: - case RISCVVector::BI__builtin_rvv_vfwcvt_xu_f_v_rm_tumu: - case RISCVVector::BI__builtin_rvv_vfncvt_x_f_w_rm_tumu: - case RISCVVector::BI__builtin_rvv_vfncvt_xu_f_w_rm_tumu: - case RISCVVector::BI__builtin_rvv_vfncvt_f_x_w_rm_tumu: - case RISCVVector::BI__builtin_rvv_vfncvt_f_xu_w_rm_tumu: - case RISCVVector::BI__builtin_rvv_vfncvt_f_f_w_rm_tumu: - case RISCVVector::BI__builtin_rvv_vfsqrt_v_rm_mu: - case RISCVVector::BI__builtin_rvv_vfrec7_v_rm_mu: - case RISCVVector::BI__builtin_rvv_vfcvt_x_f_v_rm_mu: - case RISCVVector::BI__builtin_rvv_vfcvt_xu_f_v_rm_mu: - case RISCVVector::BI__builtin_rvv_vfcvt_f_x_v_rm_mu: - case RISCVVector::BI__builtin_rvv_vfcvt_f_xu_v_rm_mu: - case RISCVVector::BI__builtin_rvv_vfwcvt_x_f_v_rm_mu: - case RISCVVector::BI__builtin_rvv_vfwcvt_xu_f_v_rm_mu: - case RISCVVector::BI__builtin_rvv_vfncvt_x_f_w_rm_mu: - case RISCVVector::BI__builtin_rvv_vfncvt_xu_f_w_rm_mu: - case RISCVVector::BI__builtin_rvv_vfncvt_f_x_w_rm_mu: - case RISCVVector::BI__builtin_rvv_vfncvt_f_xu_w_rm_mu: - case RISCVVector::BI__builtin_rvv_vfncvt_f_f_w_rm_mu: - return BuiltinConstantArgRange(TheCall, 3, 0, 4); - case RISCVVector::BI__builtin_rvv_vfmacc_vv_rm_m: - case RISCVVector::BI__builtin_rvv_vfmacc_vf_rm_m: - case RISCVVector::BI__builtin_rvv_vfnmacc_vv_rm_m: - case RISCVVector::BI__builtin_rvv_vfnmacc_vf_rm_m: - case RISCVVector::BI__builtin_rvv_vfmsac_vv_rm_m: - case RISCVVector::BI__builtin_rvv_vfmsac_vf_rm_m: - case RISCVVector::BI__builtin_rvv_vfnmsac_vv_rm_m: - case RISCVVector::BI__builtin_rvv_vfnmsac_vf_rm_m: - case RISCVVector::BI__builtin_rvv_vfmadd_vv_rm_m: - case RISCVVector::BI__builtin_rvv_vfmadd_vf_rm_m: - case RISCVVector::BI__builtin_rvv_vfnmadd_vv_rm_m: - case RISCVVector::BI__builtin_rvv_vfnmadd_vf_rm_m: - case RISCVVector::BI__builtin_rvv_vfmsub_vv_rm_m: - case RISCVVector::BI__builtin_rvv_vfmsub_vf_rm_m: - case RISCVVector::BI__builtin_rvv_vfnmsub_vv_rm_m: - case RISCVVector::BI__builtin_rvv_vfnmsub_vf_rm_m: - case RISCVVector::BI__builtin_rvv_vfwmacc_vv_rm_m: - case RISCVVector::BI__builtin_rvv_vfwmacc_vf_rm_m: - case RISCVVector::BI__builtin_rvv_vfwnmacc_vv_rm_m: - case RISCVVector::BI__builtin_rvv_vfwnmacc_vf_rm_m: - case RISCVVector::BI__builtin_rvv_vfwmsac_vv_rm_m: - case RISCVVector::BI__builtin_rvv_vfwmsac_vf_rm_m: - case RISCVVector::BI__builtin_rvv_vfwnmsac_vv_rm_m: - case RISCVVector::BI__builtin_rvv_vfwnmsac_vf_rm_m: - case RISCVVector::BI__builtin_rvv_vfadd_vv_rm_tum: - case RISCVVector::BI__builtin_rvv_vfadd_vf_rm_tum: - case RISCVVector::BI__builtin_rvv_vfsub_vv_rm_tum: - case RISCVVector::BI__builtin_rvv_vfsub_vf_rm_tum: - case RISCVVector::BI__builtin_rvv_vfrsub_vf_rm_tum: - case RISCVVector::BI__builtin_rvv_vfwadd_vv_rm_tum: - case RISCVVector::BI__builtin_rvv_vfwadd_vf_rm_tum: - case RISCVVector::BI__builtin_rvv_vfwsub_vv_rm_tum: - case RISCVVector::BI__builtin_rvv_vfwsub_vf_rm_tum: - case RISCVVector::BI__builtin_rvv_vfwadd_wv_rm_tum: - case RISCVVector::BI__builtin_rvv_vfwadd_wf_rm_tum: - case RISCVVector::BI__builtin_rvv_vfwsub_wv_rm_tum: - case RISCVVector::BI__builtin_rvv_vfwsub_wf_rm_tum: - case RISCVVector::BI__builtin_rvv_vfmul_vv_rm_tum: - case RISCVVector::BI__builtin_rvv_vfmul_vf_rm_tum: - case RISCVVector::BI__builtin_rvv_vfdiv_vv_rm_tum: - case RISCVVector::BI__builtin_rvv_vfdiv_vf_rm_tum: - case RISCVVector::BI__builtin_rvv_vfrdiv_vf_rm_tum: - case RISCVVector::BI__builtin_rvv_vfwmul_vv_rm_tum: - case RISCVVector::BI__builtin_rvv_vfwmul_vf_rm_tum: - case RISCVVector::BI__builtin_rvv_vfmacc_vv_rm_tum: - case RISCVVector::BI__builtin_rvv_vfmacc_vf_rm_tum: - case RISCVVector::BI__builtin_rvv_vfnmacc_vv_rm_tum: - case RISCVVector::BI__builtin_rvv_vfnmacc_vf_rm_tum: - case RISCVVector::BI__builtin_rvv_vfmsac_vv_rm_tum: - case RISCVVector::BI__builtin_rvv_vfmsac_vf_rm_tum: - case RISCVVector::BI__builtin_rvv_vfnmsac_vv_rm_tum: - case RISCVVector::BI__builtin_rvv_vfnmsac_vf_rm_tum: - case RISCVVector::BI__builtin_rvv_vfmadd_vv_rm_tum: - case RISCVVector::BI__builtin_rvv_vfmadd_vf_rm_tum: - case RISCVVector::BI__builtin_rvv_vfnmadd_vv_rm_tum: - case RISCVVector::BI__builtin_rvv_vfnmadd_vf_rm_tum: - case RISCVVector::BI__builtin_rvv_vfmsub_vv_rm_tum: - case RISCVVector::BI__builtin_rvv_vfmsub_vf_rm_tum: - case RISCVVector::BI__builtin_rvv_vfnmsub_vv_rm_tum: - case RISCVVector::BI__builtin_rvv_vfnmsub_vf_rm_tum: - case RISCVVector::BI__builtin_rvv_vfwmacc_vv_rm_tum: - case RISCVVector::BI__builtin_rvv_vfwmacc_vf_rm_tum: - case RISCVVector::BI__builtin_rvv_vfwnmacc_vv_rm_tum: - case RISCVVector::BI__builtin_rvv_vfwnmacc_vf_rm_tum: - case RISCVVector::BI__builtin_rvv_vfwmsac_vv_rm_tum: - case RISCVVector::BI__builtin_rvv_vfwmsac_vf_rm_tum: - case RISCVVector::BI__builtin_rvv_vfwnmsac_vv_rm_tum: - case RISCVVector::BI__builtin_rvv_vfwnmsac_vf_rm_tum: - case RISCVVector::BI__builtin_rvv_vfredosum_vs_rm_tum: - case RISCVVector::BI__builtin_rvv_vfredusum_vs_rm_tum: - case RISCVVector::BI__builtin_rvv_vfwredosum_vs_rm_tum: - case RISCVVector::BI__builtin_rvv_vfwredusum_vs_rm_tum: - case RISCVVector::BI__builtin_rvv_vfadd_vv_rm_tumu: - case RISCVVector::BI__builtin_rvv_vfadd_vf_rm_tumu: - case RISCVVector::BI__builtin_rvv_vfsub_vv_rm_tumu: - case RISCVVector::BI__builtin_rvv_vfsub_vf_rm_tumu: - case RISCVVector::BI__builtin_rvv_vfrsub_vf_rm_tumu: - case RISCVVector::BI__builtin_rvv_vfwadd_vv_rm_tumu: - case RISCVVector::BI__builtin_rvv_vfwadd_vf_rm_tumu: - case RISCVVector::BI__builtin_rvv_vfwsub_vv_rm_tumu: - case RISCVVector::BI__builtin_rvv_vfwsub_vf_rm_tumu: - case RISCVVector::BI__builtin_rvv_vfwadd_wv_rm_tumu: - case RISCVVector::BI__builtin_rvv_vfwadd_wf_rm_tumu: - case RISCVVector::BI__builtin_rvv_vfwsub_wv_rm_tumu: - case RISCVVector::BI__builtin_rvv_vfwsub_wf_rm_tumu: - case RISCVVector::BI__builtin_rvv_vfmul_vv_rm_tumu: - case RISCVVector::BI__builtin_rvv_vfmul_vf_rm_tumu: - case RISCVVector::BI__builtin_rvv_vfdiv_vv_rm_tumu: - case RISCVVector::BI__builtin_rvv_vfdiv_vf_rm_tumu: - case RISCVVector::BI__builtin_rvv_vfrdiv_vf_rm_tumu: - case RISCVVector::BI__builtin_rvv_vfwmul_vv_rm_tumu: - case RISCVVector::BI__builtin_rvv_vfwmul_vf_rm_tumu: - case RISCVVector::BI__builtin_rvv_vfmacc_vv_rm_tumu: - case RISCVVector::BI__builtin_rvv_vfmacc_vf_rm_tumu: - case RISCVVector::BI__builtin_rvv_vfnmacc_vv_rm_tumu: - case RISCVVector::BI__builtin_rvv_vfnmacc_vf_rm_tumu: - case RISCVVector::BI__builtin_rvv_vfmsac_vv_rm_tumu: - case RISCVVector::BI__builtin_rvv_vfmsac_vf_rm_tumu: - case RISCVVector::BI__builtin_rvv_vfnmsac_vv_rm_tumu: - case RISCVVector::BI__builtin_rvv_vfnmsac_vf_rm_tumu: - case RISCVVector::BI__builtin_rvv_vfmadd_vv_rm_tumu: - case RISCVVector::BI__builtin_rvv_vfmadd_vf_rm_tumu: - case RISCVVector::BI__builtin_rvv_vfnmadd_vv_rm_tumu: - case RISCVVector::BI__builtin_rvv_vfnmadd_vf_rm_tumu: - case RISCVVector::BI__builtin_rvv_vfmsub_vv_rm_tumu: - case RISCVVector::BI__builtin_rvv_vfmsub_vf_rm_tumu: - case RISCVVector::BI__builtin_rvv_vfnmsub_vv_rm_tumu: - case RISCVVector::BI__builtin_rvv_vfnmsub_vf_rm_tumu: - case RISCVVector::BI__builtin_rvv_vfwmacc_vv_rm_tumu: - case RISCVVector::BI__builtin_rvv_vfwmacc_vf_rm_tumu: - case RISCVVector::BI__builtin_rvv_vfwnmacc_vv_rm_tumu: - case RISCVVector::BI__builtin_rvv_vfwnmacc_vf_rm_tumu: - case RISCVVector::BI__builtin_rvv_vfwmsac_vv_rm_tumu: - case RISCVVector::BI__builtin_rvv_vfwmsac_vf_rm_tumu: - case RISCVVector::BI__builtin_rvv_vfwnmsac_vv_rm_tumu: - case RISCVVector::BI__builtin_rvv_vfwnmsac_vf_rm_tumu: - case RISCVVector::BI__builtin_rvv_vfadd_vv_rm_mu: - case RISCVVector::BI__builtin_rvv_vfadd_vf_rm_mu: - case RISCVVector::BI__builtin_rvv_vfsub_vv_rm_mu: - case RISCVVector::BI__builtin_rvv_vfsub_vf_rm_mu: - case RISCVVector::BI__builtin_rvv_vfrsub_vf_rm_mu: - case RISCVVector::BI__builtin_rvv_vfwadd_vv_rm_mu: - case RISCVVector::BI__builtin_rvv_vfwadd_vf_rm_mu: - case RISCVVector::BI__builtin_rvv_vfwsub_vv_rm_mu: - case RISCVVector::BI__builtin_rvv_vfwsub_vf_rm_mu: - case RISCVVector::BI__builtin_rvv_vfwadd_wv_rm_mu: - case RISCVVector::BI__builtin_rvv_vfwadd_wf_rm_mu: - case RISCVVector::BI__builtin_rvv_vfwsub_wv_rm_mu: - case RISCVVector::BI__builtin_rvv_vfwsub_wf_rm_mu: - case RISCVVector::BI__builtin_rvv_vfmul_vv_rm_mu: - case RISCVVector::BI__builtin_rvv_vfmul_vf_rm_mu: - case RISCVVector::BI__builtin_rvv_vfdiv_vv_rm_mu: - case RISCVVector::BI__builtin_rvv_vfdiv_vf_rm_mu: - case RISCVVector::BI__builtin_rvv_vfrdiv_vf_rm_mu: - case RISCVVector::BI__builtin_rvv_vfwmul_vv_rm_mu: - case RISCVVector::BI__builtin_rvv_vfwmul_vf_rm_mu: - case RISCVVector::BI__builtin_rvv_vfmacc_vv_rm_mu: - case RISCVVector::BI__builtin_rvv_vfmacc_vf_rm_mu: - case RISCVVector::BI__builtin_rvv_vfnmacc_vv_rm_mu: - case RISCVVector::BI__builtin_rvv_vfnmacc_vf_rm_mu: - case RISCVVector::BI__builtin_rvv_vfmsac_vv_rm_mu: - case RISCVVector::BI__builtin_rvv_vfmsac_vf_rm_mu: - case RISCVVector::BI__builtin_rvv_vfnmsac_vv_rm_mu: - case RISCVVector::BI__builtin_rvv_vfnmsac_vf_rm_mu: - case RISCVVector::BI__builtin_rvv_vfmadd_vv_rm_mu: - case RISCVVector::BI__builtin_rvv_vfmadd_vf_rm_mu: - case RISCVVector::BI__builtin_rvv_vfnmadd_vv_rm_mu: - case RISCVVector::BI__builtin_rvv_vfnmadd_vf_rm_mu: - case RISCVVector::BI__builtin_rvv_vfmsub_vv_rm_mu: - case RISCVVector::BI__builtin_rvv_vfmsub_vf_rm_mu: - case RISCVVector::BI__builtin_rvv_vfnmsub_vv_rm_mu: - case RISCVVector::BI__builtin_rvv_vfnmsub_vf_rm_mu: - case RISCVVector::BI__builtin_rvv_vfwmacc_vv_rm_mu: - case RISCVVector::BI__builtin_rvv_vfwmacc_vf_rm_mu: - case RISCVVector::BI__builtin_rvv_vfwnmacc_vv_rm_mu: - case RISCVVector::BI__builtin_rvv_vfwnmacc_vf_rm_mu: - case RISCVVector::BI__builtin_rvv_vfwmsac_vv_rm_mu: - case RISCVVector::BI__builtin_rvv_vfwmsac_vf_rm_mu: - case RISCVVector::BI__builtin_rvv_vfwnmsac_vv_rm_mu: - case RISCVVector::BI__builtin_rvv_vfwnmsac_vf_rm_mu: - return BuiltinConstantArgRange(TheCall, 4, 0, 4); - case RISCV::BI__builtin_riscv_ntl_load: - case RISCV::BI__builtin_riscv_ntl_store: - DeclRefExpr *DRE = - cast(TheCall->getCallee()->IgnoreParenCasts()); - assert((BuiltinID == RISCV::BI__builtin_riscv_ntl_store || - BuiltinID == RISCV::BI__builtin_riscv_ntl_load) && - "Unexpected RISC-V nontemporal load/store builtin!"); - bool IsStore = BuiltinID == RISCV::BI__builtin_riscv_ntl_store; - unsigned NumArgs = IsStore ? 3 : 2; - - if (checkArgCountAtLeast(*this, TheCall, NumArgs - 1)) - return true; - - if (checkArgCountAtMost(*this, TheCall, NumArgs)) - return true; - - // Domain value should be compile-time constant. - // 2 <= domain <= 5 - if (TheCall->getNumArgs() == NumArgs && - BuiltinConstantArgRange(TheCall, NumArgs - 1, 2, 5)) - return true; - - Expr *PointerArg = TheCall->getArg(0); - ExprResult PointerArgResult = - DefaultFunctionArrayLvalueConversion(PointerArg); - - if (PointerArgResult.isInvalid()) - return true; - PointerArg = PointerArgResult.get(); - - const PointerType *PtrType = PointerArg->getType()->getAs(); - if (!PtrType) { - Diag(DRE->getBeginLoc(), diag::err_nontemporal_builtin_must_be_pointer) - << PointerArg->getType() << PointerArg->getSourceRange(); - return true; - } - - QualType ValType = PtrType->getPointeeType(); - ValType = ValType.getUnqualifiedType(); - if (!ValType->isIntegerType() && !ValType->isAnyPointerType() && - !ValType->isBlockPointerType() && !ValType->isFloatingType() && - !ValType->isVectorType() && !ValType->isRVVSizelessBuiltinType()) { - Diag(DRE->getBeginLoc(), - diag::err_nontemporal_builtin_must_be_pointer_intfltptr_or_vector) - << PointerArg->getType() << PointerArg->getSourceRange(); - return true; - } - - if (!IsStore) { - TheCall->setType(ValType); - return false; - } - - ExprResult ValArg = TheCall->getArg(1); - InitializedEntity Entity = InitializedEntity::InitializeParameter( - Context, ValType, /*consume*/ false); - ValArg = PerformCopyInitialization(Entity, SourceLocation(), ValArg); - if (ValArg.isInvalid()) - return true; - - TheCall->setArg(1, ValArg.get()); - TheCall->setType(Context.VoidTy); - return false; - } - - return false; -} - bool Sema::CheckSystemZBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) { if (BuiltinID == SystemZ::BI__builtin_tabort) { @@ -6708,38 +5849,6 @@ bool Sema::CheckWebAssemblyBuiltinFunctionCall(const TargetInfo &TI, return false; } -void Sema::checkRVVTypeSupport(QualType Ty, SourceLocation Loc, Decl *D, - const llvm::StringMap &FeatureMap) { - ASTContext::BuiltinVectorTypeInfo Info = - Context.getBuiltinVectorTypeInfo(Ty->castAs()); - unsigned EltSize = Context.getTypeSize(Info.ElementType); - unsigned MinElts = Info.EC.getKnownMinValue(); - - if (Info.ElementType->isSpecificBuiltinType(BuiltinType::Double) && - !FeatureMap.lookup("zve64d")) - Diag(Loc, diag::err_riscv_type_requires_extension, D) << Ty << "zve64d"; - // (ELEN, LMUL) pairs of (8, mf8), (16, mf4), (32, mf2), (64, m1) requires at - // least zve64x - else if (((EltSize == 64 && Info.ElementType->isIntegerType()) || - MinElts == 1) && - !FeatureMap.lookup("zve64x")) - Diag(Loc, diag::err_riscv_type_requires_extension, D) << Ty << "zve64x"; - else if (Info.ElementType->isFloat16Type() && !FeatureMap.lookup("zvfh") && - !FeatureMap.lookup("zvfhmin")) - Diag(Loc, diag::err_riscv_type_requires_extension, D) - << Ty << "zvfh or zvfhmin"; - else if (Info.ElementType->isBFloat16Type() && - !FeatureMap.lookup("experimental-zvfbfmin")) - Diag(Loc, diag::err_riscv_type_requires_extension, D) << Ty << "zvfbfmin"; - else if (Info.ElementType->isSpecificBuiltinType(BuiltinType::Float) && - !FeatureMap.lookup("zve32f")) - Diag(Loc, diag::err_riscv_type_requires_extension, D) << Ty << "zve32f"; - // Given that caller already checked isRVVType() before calling this function, - // if we don't have at least zve32x supported, then we need to emit error. - else if (!FeatureMap.lookup("zve32x")) - Diag(Loc, diag::err_riscv_type_requires_extension, D) << Ty << "zve32x"; -} - bool Sema::CheckNVPTXBuiltinFunctionCall(const TargetInfo &TI, unsigned BuiltinID, CallExpr *TheCall) { @@ -6748,7 +5857,7 @@ bool Sema::CheckNVPTXBuiltinFunctionCall(const TargetInfo &TI, case NVPTX::BI__nvvm_cp_async_ca_shared_global_8: case NVPTX::BI__nvvm_cp_async_ca_shared_global_16: case NVPTX::BI__nvvm_cp_async_cg_shared_global_16: - return checkArgCountAtMost(*this, TheCall, 3); + return checkArgCountAtMost(TheCall, 3); } return false; @@ -9302,7 +8411,7 @@ ExprResult Sema::BuiltinNontemporalOverloaded(ExprResult TheCallResult) { unsigned numArgs = isStore ? 2 : 1; // Ensure that we have the proper number of arguments. - if (checkArgCount(*this, TheCall, numArgs)) + if (checkArgCount(TheCall, numArgs)) return ExprError(); // Inspect the last argument of the nontemporal builtin. This should always @@ -9467,7 +8576,7 @@ bool Sema::BuiltinVAStart(unsigned BuiltinID, CallExpr *TheCall) { // In C23 mode, va_start only needs one argument. However, the builtin still // requires two arguments (which matches the behavior of the GCC builtin), // passes `0` as the second argument in C23 mode. - if (checkArgCount(*this, TheCall, 2)) + if (checkArgCount(TheCall, 2)) return true; // Type-check the first argument normally. @@ -9598,7 +8707,7 @@ bool Sema::BuiltinVAStartARMMicrosoft(CallExpr *Call) { /// BuiltinUnorderedCompare - Handle functions like __builtin_isgreater and /// friends. This is declared to take (...), so we have to check everything. bool Sema::BuiltinUnorderedCompare(CallExpr *TheCall, unsigned BuiltinID) { - if (checkArgCount(*this, TheCall, 2)) + if (checkArgCount(TheCall, 2)) return true; if (BuiltinID == Builtin::BI__builtin_isunordered && @@ -9642,7 +8751,7 @@ bool Sema::BuiltinUnorderedCompare(CallExpr *TheCall, unsigned BuiltinID) { /// to check everything. bool Sema::BuiltinFPClassification(CallExpr *TheCall, unsigned NumArgs, unsigned BuiltinID) { - if (checkArgCount(*this, TheCall, NumArgs)) + if (checkArgCount(TheCall, NumArgs)) return true; FPOptions FPO = TheCall->getFPFeaturesInEffect(getLangOpts()); @@ -9727,7 +8836,7 @@ bool Sema::BuiltinFPClassification(CallExpr *TheCall, unsigned NumArgs, /// Perform semantic analysis for a call to __builtin_complex. bool Sema::BuiltinComplex(CallExpr *TheCall) { - if (checkArgCount(*this, TheCall, 2)) + if (checkArgCount(TheCall, 2)) return true; bool Dependent = false; @@ -9789,7 +8898,7 @@ bool Sema::BuiltinComplex(CallExpr *TheCall) { // vector short vec_xxsldwi(vector short, vector short, int); bool Sema::BuiltinVSX(CallExpr *TheCall) { unsigned ExpectedNumArgs = 3; - if (checkArgCount(*this, TheCall, ExpectedNumArgs)) + if (checkArgCount(TheCall, ExpectedNumArgs)) return true; // Check the third argument is a compile time constant @@ -9976,7 +9085,7 @@ bool Sema::BuiltinArithmeticFence(CallExpr *TheCall) { if (!Context.getTargetInfo().checkArithmeticFenceSupported()) return Diag(TheCall->getBeginLoc(), diag::err_builtin_target_unsupported) << SourceRange(TheCall->getBeginLoc(), TheCall->getEndLoc()); - if (checkArgCount(*this, TheCall, 1)) + if (checkArgCount(TheCall, 1)) return true; Expr *Arg = TheCall->getArg(0); if (Arg->isInstantiationDependent()) @@ -10046,7 +9155,7 @@ bool Sema::BuiltinAllocaWithAlign(CallExpr *TheCall) { /// Handle __builtin_assume_aligned. This is declared /// as (const void*, size_t, ...) and can take one optional constant int arg. bool Sema::BuiltinAssumeAligned(CallExpr *TheCall) { - if (checkArgCountRange(*this, TheCall, 2, 3)) + if (checkArgCountRange(TheCall, 2, 3)) return true; unsigned NumArgs = TheCall->getNumArgs(); @@ -10349,7 +9458,7 @@ bool Sema::BuiltinConstantArgShiftedByteOrXXFF(CallExpr *TheCall, int ArgNum, /// BuiltinARMMemoryTaggingCall - Handle calls of memory tagging extensions bool Sema::BuiltinARMMemoryTaggingCall(unsigned BuiltinID, CallExpr *TheCall) { if (BuiltinID == AArch64::BI__builtin_arm_irg) { - if (checkArgCount(*this, TheCall, 2)) + if (checkArgCount(TheCall, 2)) return true; Expr *Arg0 = TheCall->getArg(0); Expr *Arg1 = TheCall->getArg(1); @@ -10377,7 +9486,7 @@ bool Sema::BuiltinARMMemoryTaggingCall(unsigned BuiltinID, CallExpr *TheCall) { } if (BuiltinID == AArch64::BI__builtin_arm_addg) { - if (checkArgCount(*this, TheCall, 2)) + if (checkArgCount(TheCall, 2)) return true; Expr *Arg0 = TheCall->getArg(0); @@ -10398,7 +9507,7 @@ bool Sema::BuiltinARMMemoryTaggingCall(unsigned BuiltinID, CallExpr *TheCall) { } if (BuiltinID == AArch64::BI__builtin_arm_gmi) { - if (checkArgCount(*this, TheCall, 2)) + if (checkArgCount(TheCall, 2)) return true; Expr *Arg0 = TheCall->getArg(0); Expr *Arg1 = TheCall->getArg(1); @@ -10421,7 +9530,7 @@ bool Sema::BuiltinARMMemoryTaggingCall(unsigned BuiltinID, CallExpr *TheCall) { if (BuiltinID == AArch64::BI__builtin_arm_ldg || BuiltinID == AArch64::BI__builtin_arm_stg) { - if (checkArgCount(*this, TheCall, 1)) + if (checkArgCount(TheCall, 1)) return true; Expr *Arg0 = TheCall->getArg(0); ExprResult FirstArg = DefaultFunctionArrayLvalueConversion(Arg0); @@ -10694,7 +9803,7 @@ bool Sema::BuiltinPPCMMACall(CallExpr *TheCall, unsigned BuiltinID, (void) DecodePPCMMATypeFromStr(Context, TypeStr, Mask); ArgNum++; } - if (checkArgCount(*this, TheCall, ArgNum)) + if (checkArgCount(TheCall, ArgNum)) return true; return false; @@ -19706,7 +18815,7 @@ void Sema::CheckAddressOfPackedMember(Expr *rhs) { } bool Sema::PrepareBuiltinElementwiseMathOneArgCall(CallExpr *TheCall) { - if (checkArgCount(*this, TheCall, 1)) + if (checkArgCount(TheCall, 1)) return true; ExprResult A = UsualUnaryConversions(TheCall->getArg(0)); @@ -19745,7 +18854,7 @@ bool Sema::BuiltinVectorToScalarMath(CallExpr *TheCall) { } bool Sema::BuiltinVectorMath(CallExpr *TheCall, QualType &Res) { - if (checkArgCount(*this, TheCall, 2)) + if (checkArgCount(TheCall, 2)) return true; ExprResult A = TheCall->getArg(0); @@ -19774,7 +18883,7 @@ bool Sema::BuiltinVectorMath(CallExpr *TheCall, QualType &Res) { bool Sema::BuiltinElementwiseTernaryMath(CallExpr *TheCall, bool CheckForFloatArgs) { - if (checkArgCount(*this, TheCall, 3)) + if (checkArgCount(TheCall, 3)) return true; Expr *Args[3]; @@ -19817,7 +18926,7 @@ bool Sema::BuiltinElementwiseTernaryMath(CallExpr *TheCall, } bool Sema::PrepareBuiltinReduceMathOneArgCall(CallExpr *TheCall) { - if (checkArgCount(*this, TheCall, 1)) + if (checkArgCount(TheCall, 1)) return true; ExprResult A = UsualUnaryConversions(TheCall->getArg(0)); @@ -19829,7 +18938,7 @@ bool Sema::PrepareBuiltinReduceMathOneArgCall(CallExpr *TheCall) { } bool Sema::BuiltinNonDeterministicValue(CallExpr *TheCall) { - if (checkArgCount(*this, TheCall, 1)) + if (checkArgCount(TheCall, 1)) return true; ExprResult Arg = TheCall->getArg(0); @@ -19845,7 +18954,7 @@ bool Sema::BuiltinNonDeterministicValue(CallExpr *TheCall) { ExprResult Sema::BuiltinMatrixTranspose(CallExpr *TheCall, ExprResult CallResult) { - if (checkArgCount(*this, TheCall, 1)) + if (checkArgCount(TheCall, 1)) return ExprError(); ExprResult MatrixArg = DefaultLvalueConversion(TheCall->getArg(0)); @@ -19900,7 +19009,7 @@ ExprResult Sema::BuiltinMatrixColumnMajorLoad(CallExpr *TheCall, return ExprError(); } - if (checkArgCount(*this, TheCall, 4)) + if (checkArgCount(TheCall, 4)) return ExprError(); unsigned PtrArgIdx = 0; @@ -20011,7 +19120,7 @@ ExprResult Sema::BuiltinMatrixColumnMajorLoad(CallExpr *TheCall, ExprResult Sema::BuiltinMatrixColumnMajorStore(CallExpr *TheCall, ExprResult CallResult) { - if (checkArgCount(*this, TheCall, 3)) + if (checkArgCount(TheCall, 3)) return ExprError(); unsigned PtrArgIdx = 1; @@ -20137,7 +19246,7 @@ static bool CheckWasmBuiltinArgIsInteger(Sema &S, CallExpr *E, /// Check that the first argument is a WebAssembly table, and the second /// is an index to use as index into the table. bool Sema::BuiltinWasmTableGet(CallExpr *TheCall) { - if (checkArgCount(*this, TheCall, 2)) + if (checkArgCount(TheCall, 2)) return true; QualType ElTy; @@ -20160,7 +19269,7 @@ bool Sema::BuiltinWasmTableGet(CallExpr *TheCall) { /// an index to use as index into the table and the third is the reference /// type to set into the table. bool Sema::BuiltinWasmTableSet(CallExpr *TheCall) { - if (checkArgCount(*this, TheCall, 3)) + if (checkArgCount(TheCall, 3)) return true; QualType ElTy; @@ -20178,7 +19287,7 @@ bool Sema::BuiltinWasmTableSet(CallExpr *TheCall) { /// Check that the argument is a WebAssembly table. bool Sema::BuiltinWasmTableSize(CallExpr *TheCall) { - if (checkArgCount(*this, TheCall, 1)) + if (checkArgCount(TheCall, 1)) return true; QualType ElTy; @@ -20192,7 +19301,7 @@ bool Sema::BuiltinWasmTableSize(CallExpr *TheCall) { /// value to use for new elements (of a type matching the table type), the /// third value is an integer. bool Sema::BuiltinWasmTableGrow(CallExpr *TheCall) { - if (checkArgCount(*this, TheCall, 3)) + if (checkArgCount(TheCall, 3)) return true; QualType ElTy; @@ -20216,7 +19325,7 @@ bool Sema::BuiltinWasmTableGrow(CallExpr *TheCall) { /// integer, the third is the value to use to fill the table (of a type /// matching the table type), and the fourth is an integer. bool Sema::BuiltinWasmTableFill(CallExpr *TheCall) { - if (checkArgCount(*this, TheCall, 4)) + if (checkArgCount(TheCall, 4)) return true; QualType ElTy; @@ -20243,7 +19352,7 @@ bool Sema::BuiltinWasmTableFill(CallExpr *TheCall) { /// WebAssembly table (of the same element type), and the third to fifth /// arguments are integers. bool Sema::BuiltinWasmTableCopy(CallExpr *TheCall) { - if (checkArgCount(*this, TheCall, 5)) + if (checkArgCount(TheCall, 5)) return true; QualType XElTy; diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index 8049ddfed872..b5c3a27ab06e 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -50,6 +50,7 @@ #include "clang/Sema/SemaInternal.h" #include "clang/Sema/SemaObjC.h" #include "clang/Sema/SemaOpenMP.h" +#include "clang/Sema/SemaRISCV.h" #include "clang/Sema/Template.h" #include "llvm/ADT/STLForwardCompat.h" #include "llvm/ADT/SmallString.h" @@ -8926,8 +8927,8 @@ void Sema::CheckVariableDeclarationType(VarDecl *NewVD) { const FunctionDecl *FD = cast(CurContext); llvm::StringMap CallerFeatureMap; Context.getFunctionFeatureMap(CallerFeatureMap, FD); - checkRVVTypeSupport(T, NewVD->getLocation(), cast(CurContext), - CallerFeatureMap); + RISCV().checkRVVTypeSupport(T, NewVD->getLocation(), cast(CurContext), + CallerFeatureMap); } } diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index 326879b0883f..f0ad3de31138 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -7527,27 +7527,6 @@ bool Sema::isValidSveBitcast(QualType srcTy, QualType destTy) { ValidScalableConversion(destTy, srcTy); } -/// Are the two types RVV-bitcast-compatible types? I.e. is bitcasting from the -/// first RVV type (e.g. an RVV scalable type) to the second type (e.g. an RVV -/// VLS type) allowed? -/// -/// This will also return false if the two given types do not make sense from -/// the perspective of RVV bitcasts. -bool Sema::isValidRVVBitcast(QualType srcTy, QualType destTy) { - assert(srcTy->isVectorType() || destTy->isVectorType()); - - auto ValidScalableConversion = [](QualType FirstType, QualType SecondType) { - if (!FirstType->isRVVSizelessBuiltinType()) - return false; - - const auto *VecTy = SecondType->getAs(); - return VecTy && VecTy->getVectorKind() == VectorKind::RVVFixedLengthData; - }; - - return ValidScalableConversion(srcTy, destTy) || - ValidScalableConversion(destTy, srcTy); -} - /// Are the two types matrix types and do they have the same dimensions i.e. /// do they have the same number of rows and the same number of columns? bool Sema::areMatrixTypesOfTheSameDimension(QualType srcTy, QualType destTy) { diff --git a/clang/lib/Sema/SemaLookup.cpp b/clang/lib/Sema/SemaLookup.cpp index e4d4cd7395eb..ef0a655b631a 100644 --- a/clang/lib/Sema/SemaLookup.cpp +++ b/clang/lib/Sema/SemaLookup.cpp @@ -34,6 +34,7 @@ #include "clang/Sema/ScopeInfo.h" #include "clang/Sema/Sema.h" #include "clang/Sema/SemaInternal.h" +#include "clang/Sema/SemaRISCV.h" #include "clang/Sema/TemplateDeduction.h" #include "clang/Sema/TypoCorrection.h" #include "llvm/ADT/STLExtras.h" @@ -945,13 +946,13 @@ bool Sema::LookupBuiltin(LookupResult &R) { } } - if (DeclareRISCVVBuiltins || DeclareRISCVSiFiveVectorBuiltins) { - if (!RVIntrinsicManager) - RVIntrinsicManager = CreateRISCVIntrinsicManager(*this); + if (RISCV().DeclareRVVBuiltins || RISCV().DeclareSiFiveVectorBuiltins) { + if (!RISCV().IntrinsicManager) + RISCV().IntrinsicManager = CreateRISCVIntrinsicManager(*this); - RVIntrinsicManager->InitIntrinsicList(); + RISCV().IntrinsicManager->InitIntrinsicList(); - if (RVIntrinsicManager->CreateIntrinsicIfFound(R, II, PP)) + if (RISCV().IntrinsicManager->CreateIntrinsicIfFound(R, II, PP)) return true; } diff --git a/clang/lib/Sema/SemaRISCV.cpp b/clang/lib/Sema/SemaRISCV.cpp index 26e13e87b1d6..ea6e3f75490b 100644 --- a/clang/lib/Sema/SemaRISCV.cpp +++ b/clang/lib/Sema/SemaRISCV.cpp @@ -1,4 +1,4 @@ -//==- SemaRISCVVectorLookup.cpp - Name Lookup for RISC-V Vector Intrinsic -==// +//===------ SemaRISCV.cpp ------- RISC-V target-specific routines ---------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. @@ -6,20 +6,24 @@ // //===----------------------------------------------------------------------===// // -// This file implements name lookup for RISC-V vector intrinsic. +// This file implements semantic analysis functions specific to RISC-V. // //===----------------------------------------------------------------------===// +#include "clang/Sema/SemaRISCV.h" #include "clang/AST/ASTContext.h" #include "clang/AST/Decl.h" #include "clang/Basic/Builtins.h" +#include "clang/Basic/TargetBuiltins.h" #include "clang/Basic/TargetInfo.h" #include "clang/Lex/Preprocessor.h" +#include "clang/Sema/Initialization.h" #include "clang/Sema/Lookup.h" #include "clang/Sema/RISCVIntrinsicManager.h" #include "clang/Sema/Sema.h" #include "clang/Support/RISCVVIntrinsicUtils.h" #include "llvm/ADT/SmallVector.h" +#include "llvm/TargetParser/RISCVTargetParser.h" #include #include #include @@ -166,7 +170,6 @@ private: // Mapping function name to RVVOverloadIntrinsicDef. StringMap OverloadIntrinsics; - // Create RVVIntrinsicDef. void InitRVVIntrinsic(const RVVIntrinsicRecord &Record, StringRef SuffixStr, StringRef OverloadedSuffixStr, bool IsMask, @@ -342,18 +345,17 @@ void RISCVIntrinsicManagerImpl::ConstructRVVIntrinsics( /*IsMask=*/true, *PolicyTypes, MaskedHasPolicy, P); } } // End for different LMUL - } // End for different TypeRange + } // End for different TypeRange } } void RISCVIntrinsicManagerImpl::InitIntrinsicList() { - if (S.DeclareRISCVVBuiltins && !ConstructedRISCVVBuiltins) { + if (S.RISCV().DeclareRVVBuiltins && !ConstructedRISCVVBuiltins) { ConstructedRISCVVBuiltins = true; - ConstructRVVIntrinsics(RVVIntrinsicRecords, - IntrinsicKind::RVV); + ConstructRVVIntrinsics(RVVIntrinsicRecords, IntrinsicKind::RVV); } - if (S.DeclareRISCVSiFiveVectorBuiltins && + if (S.RISCV().DeclareSiFiveVectorBuiltins && !ConstructedRISCVSiFiveVectorBuiltins) { ConstructedRISCVSiFiveVectorBuiltins = true; ConstructRVVIntrinsics(RVSiFiveVectorIntrinsicRecords, @@ -501,4 +503,925 @@ std::unique_ptr CreateRISCVIntrinsicManager(Sema &S) { return std::make_unique(S); } + +bool SemaRISCV::CheckLMUL(CallExpr *TheCall, unsigned ArgNum) { + llvm::APSInt Result; + + // We can't check the value of a dependent argument. + Expr *Arg = TheCall->getArg(ArgNum); + if (Arg->isTypeDependent() || Arg->isValueDependent()) + return false; + + // Check constant-ness first. + if (SemaRef.BuiltinConstantArg(TheCall, ArgNum, Result)) + return true; + + int64_t Val = Result.getSExtValue(); + if ((Val >= 0 && Val <= 3) || (Val >= 5 && Val <= 7)) + return false; + + return Diag(TheCall->getBeginLoc(), diag::err_riscv_builtin_invalid_lmul) + << Arg->getSourceRange(); +} + +static bool CheckInvalidVLENandLMUL(const TargetInfo &TI, CallExpr *TheCall, + Sema &S, QualType Type, int EGW) { + assert((EGW == 128 || EGW == 256) && "EGW can only be 128 or 256 bits"); + + // LMUL * VLEN >= EGW + ASTContext::BuiltinVectorTypeInfo Info = + S.Context.getBuiltinVectorTypeInfo(Type->castAs()); + unsigned ElemSize = S.Context.getTypeSize(Info.ElementType); + unsigned MinElemCount = Info.EC.getKnownMinValue(); + + unsigned EGS = EGW / ElemSize; + // If EGS is less than or equal to the minimum number of elements, then the + // type is valid. + if (EGS <= MinElemCount) + return false; + + // Otherwise, we need vscale to be at least EGS / MinElemCont. + assert(EGS % MinElemCount == 0); + unsigned VScaleFactor = EGS / MinElemCount; + // Vscale is VLEN/RVVBitsPerBlock. + unsigned MinRequiredVLEN = VScaleFactor * llvm::RISCV::RVVBitsPerBlock; + std::string RequiredExt = "zvl" + std::to_string(MinRequiredVLEN) + "b"; + if (!TI.hasFeature(RequiredExt)) + return S.Diag(TheCall->getBeginLoc(), + diag::err_riscv_type_requires_extension) + << Type << RequiredExt; + + return false; +} + +bool SemaRISCV::CheckBuiltinFunctionCall(const TargetInfo &TI, + unsigned BuiltinID, + CallExpr *TheCall) { + ASTContext &Context = getASTContext(); + // vmulh.vv, vmulh.vx, vmulhu.vv, vmulhu.vx, vmulhsu.vv, vmulhsu.vx, + // vsmul.vv, vsmul.vx are not included for EEW=64 in Zve64*. + switch (BuiltinID) { + default: + break; + case RISCVVector::BI__builtin_rvv_vmulhsu_vv: + case RISCVVector::BI__builtin_rvv_vmulhsu_vx: + case RISCVVector::BI__builtin_rvv_vmulhsu_vv_tu: + case RISCVVector::BI__builtin_rvv_vmulhsu_vx_tu: + case RISCVVector::BI__builtin_rvv_vmulhsu_vv_m: + case RISCVVector::BI__builtin_rvv_vmulhsu_vx_m: + case RISCVVector::BI__builtin_rvv_vmulhsu_vv_mu: + case RISCVVector::BI__builtin_rvv_vmulhsu_vx_mu: + case RISCVVector::BI__builtin_rvv_vmulhsu_vv_tum: + case RISCVVector::BI__builtin_rvv_vmulhsu_vx_tum: + case RISCVVector::BI__builtin_rvv_vmulhsu_vv_tumu: + case RISCVVector::BI__builtin_rvv_vmulhsu_vx_tumu: + case RISCVVector::BI__builtin_rvv_vmulhu_vv: + case RISCVVector::BI__builtin_rvv_vmulhu_vx: + case RISCVVector::BI__builtin_rvv_vmulhu_vv_tu: + case RISCVVector::BI__builtin_rvv_vmulhu_vx_tu: + case RISCVVector::BI__builtin_rvv_vmulhu_vv_m: + case RISCVVector::BI__builtin_rvv_vmulhu_vx_m: + case RISCVVector::BI__builtin_rvv_vmulhu_vv_mu: + case RISCVVector::BI__builtin_rvv_vmulhu_vx_mu: + case RISCVVector::BI__builtin_rvv_vmulhu_vv_tum: + case RISCVVector::BI__builtin_rvv_vmulhu_vx_tum: + case RISCVVector::BI__builtin_rvv_vmulhu_vv_tumu: + case RISCVVector::BI__builtin_rvv_vmulhu_vx_tumu: + case RISCVVector::BI__builtin_rvv_vmulh_vv: + case RISCVVector::BI__builtin_rvv_vmulh_vx: + case RISCVVector::BI__builtin_rvv_vmulh_vv_tu: + case RISCVVector::BI__builtin_rvv_vmulh_vx_tu: + case RISCVVector::BI__builtin_rvv_vmulh_vv_m: + case RISCVVector::BI__builtin_rvv_vmulh_vx_m: + case RISCVVector::BI__builtin_rvv_vmulh_vv_mu: + case RISCVVector::BI__builtin_rvv_vmulh_vx_mu: + case RISCVVector::BI__builtin_rvv_vmulh_vv_tum: + case RISCVVector::BI__builtin_rvv_vmulh_vx_tum: + case RISCVVector::BI__builtin_rvv_vmulh_vv_tumu: + case RISCVVector::BI__builtin_rvv_vmulh_vx_tumu: + case RISCVVector::BI__builtin_rvv_vsmul_vv: + case RISCVVector::BI__builtin_rvv_vsmul_vx: + case RISCVVector::BI__builtin_rvv_vsmul_vv_tu: + case RISCVVector::BI__builtin_rvv_vsmul_vx_tu: + case RISCVVector::BI__builtin_rvv_vsmul_vv_m: + case RISCVVector::BI__builtin_rvv_vsmul_vx_m: + case RISCVVector::BI__builtin_rvv_vsmul_vv_mu: + case RISCVVector::BI__builtin_rvv_vsmul_vx_mu: + case RISCVVector::BI__builtin_rvv_vsmul_vv_tum: + case RISCVVector::BI__builtin_rvv_vsmul_vx_tum: + case RISCVVector::BI__builtin_rvv_vsmul_vv_tumu: + case RISCVVector::BI__builtin_rvv_vsmul_vx_tumu: { + ASTContext::BuiltinVectorTypeInfo Info = Context.getBuiltinVectorTypeInfo( + TheCall->getType()->castAs()); + + if (Context.getTypeSize(Info.ElementType) == 64 && !TI.hasFeature("v")) + return Diag(TheCall->getBeginLoc(), + diag::err_riscv_builtin_requires_extension) + << /* IsExtension */ true << TheCall->getSourceRange() << "v"; + + break; + } + } + + switch (BuiltinID) { + case RISCVVector::BI__builtin_rvv_vsetvli: + return SemaRef.BuiltinConstantArgRange(TheCall, 1, 0, 3) || + CheckLMUL(TheCall, 2); + case RISCVVector::BI__builtin_rvv_vsetvlimax: + return SemaRef.BuiltinConstantArgRange(TheCall, 0, 0, 3) || + CheckLMUL(TheCall, 1); + case RISCVVector::BI__builtin_rvv_vget_v: { + ASTContext::BuiltinVectorTypeInfo ResVecInfo = + Context.getBuiltinVectorTypeInfo(cast( + TheCall->getType().getCanonicalType().getTypePtr())); + ASTContext::BuiltinVectorTypeInfo VecInfo = + Context.getBuiltinVectorTypeInfo(cast( + TheCall->getArg(0)->getType().getCanonicalType().getTypePtr())); + unsigned MaxIndex; + if (VecInfo.NumVectors != 1) // vget for tuple type + MaxIndex = VecInfo.NumVectors; + else // vget for non-tuple type + MaxIndex = (VecInfo.EC.getKnownMinValue() * VecInfo.NumVectors) / + (ResVecInfo.EC.getKnownMinValue() * ResVecInfo.NumVectors); + return SemaRef.BuiltinConstantArgRange(TheCall, 1, 0, MaxIndex - 1); + } + case RISCVVector::BI__builtin_rvv_vset_v: { + ASTContext::BuiltinVectorTypeInfo ResVecInfo = + Context.getBuiltinVectorTypeInfo(cast( + TheCall->getType().getCanonicalType().getTypePtr())); + ASTContext::BuiltinVectorTypeInfo VecInfo = + Context.getBuiltinVectorTypeInfo(cast( + TheCall->getArg(2)->getType().getCanonicalType().getTypePtr())); + unsigned MaxIndex; + if (ResVecInfo.NumVectors != 1) // vset for tuple type + MaxIndex = ResVecInfo.NumVectors; + else // vset fo non-tuple type + MaxIndex = (ResVecInfo.EC.getKnownMinValue() * ResVecInfo.NumVectors) / + (VecInfo.EC.getKnownMinValue() * VecInfo.NumVectors); + return SemaRef.BuiltinConstantArgRange(TheCall, 1, 0, MaxIndex - 1); + } + // Vector Crypto + case RISCVVector::BI__builtin_rvv_vaeskf1_vi_tu: + case RISCVVector::BI__builtin_rvv_vaeskf2_vi_tu: + case RISCVVector::BI__builtin_rvv_vaeskf2_vi: + case RISCVVector::BI__builtin_rvv_vsm4k_vi_tu: { + QualType Op1Type = TheCall->getArg(0)->getType(); + QualType Op2Type = TheCall->getArg(1)->getType(); + return CheckInvalidVLENandLMUL(TI, TheCall, SemaRef, Op1Type, 128) || + CheckInvalidVLENandLMUL(TI, TheCall, SemaRef, Op2Type, 128) || + SemaRef.BuiltinConstantArgRange(TheCall, 2, 0, 31); + } + case RISCVVector::BI__builtin_rvv_vsm3c_vi_tu: + case RISCVVector::BI__builtin_rvv_vsm3c_vi: { + QualType Op1Type = TheCall->getArg(0)->getType(); + return CheckInvalidVLENandLMUL(TI, TheCall, SemaRef, Op1Type, 256) || + SemaRef.BuiltinConstantArgRange(TheCall, 2, 0, 31); + } + case RISCVVector::BI__builtin_rvv_vaeskf1_vi: + case RISCVVector::BI__builtin_rvv_vsm4k_vi: { + QualType Op1Type = TheCall->getArg(0)->getType(); + return CheckInvalidVLENandLMUL(TI, TheCall, SemaRef, Op1Type, 128) || + SemaRef.BuiltinConstantArgRange(TheCall, 1, 0, 31); + } + case RISCVVector::BI__builtin_rvv_vaesdf_vv: + case RISCVVector::BI__builtin_rvv_vaesdf_vs: + case RISCVVector::BI__builtin_rvv_vaesdm_vv: + case RISCVVector::BI__builtin_rvv_vaesdm_vs: + case RISCVVector::BI__builtin_rvv_vaesef_vv: + case RISCVVector::BI__builtin_rvv_vaesef_vs: + case RISCVVector::BI__builtin_rvv_vaesem_vv: + case RISCVVector::BI__builtin_rvv_vaesem_vs: + case RISCVVector::BI__builtin_rvv_vaesz_vs: + case RISCVVector::BI__builtin_rvv_vsm4r_vv: + case RISCVVector::BI__builtin_rvv_vsm4r_vs: + case RISCVVector::BI__builtin_rvv_vaesdf_vv_tu: + case RISCVVector::BI__builtin_rvv_vaesdf_vs_tu: + case RISCVVector::BI__builtin_rvv_vaesdm_vv_tu: + case RISCVVector::BI__builtin_rvv_vaesdm_vs_tu: + case RISCVVector::BI__builtin_rvv_vaesef_vv_tu: + case RISCVVector::BI__builtin_rvv_vaesef_vs_tu: + case RISCVVector::BI__builtin_rvv_vaesem_vv_tu: + case RISCVVector::BI__builtin_rvv_vaesem_vs_tu: + case RISCVVector::BI__builtin_rvv_vaesz_vs_tu: + case RISCVVector::BI__builtin_rvv_vsm4r_vv_tu: + case RISCVVector::BI__builtin_rvv_vsm4r_vs_tu: { + QualType Op1Type = TheCall->getArg(0)->getType(); + QualType Op2Type = TheCall->getArg(1)->getType(); + return CheckInvalidVLENandLMUL(TI, TheCall, SemaRef, Op1Type, 128) || + CheckInvalidVLENandLMUL(TI, TheCall, SemaRef, Op2Type, 128); + } + case RISCVVector::BI__builtin_rvv_vsha2ch_vv: + case RISCVVector::BI__builtin_rvv_vsha2cl_vv: + case RISCVVector::BI__builtin_rvv_vsha2ms_vv: + case RISCVVector::BI__builtin_rvv_vsha2ch_vv_tu: + case RISCVVector::BI__builtin_rvv_vsha2cl_vv_tu: + case RISCVVector::BI__builtin_rvv_vsha2ms_vv_tu: { + QualType Op1Type = TheCall->getArg(0)->getType(); + QualType Op2Type = TheCall->getArg(1)->getType(); + QualType Op3Type = TheCall->getArg(2)->getType(); + ASTContext::BuiltinVectorTypeInfo Info = + Context.getBuiltinVectorTypeInfo(Op1Type->castAs()); + uint64_t ElemSize = Context.getTypeSize(Info.ElementType); + if (ElemSize == 64 && !TI.hasFeature("zvknhb")) + return Diag(TheCall->getBeginLoc(), + diag::err_riscv_builtin_requires_extension) + << /* IsExtension */ true << TheCall->getSourceRange() << "zvknb"; + + return CheckInvalidVLENandLMUL(TI, TheCall, SemaRef, Op1Type, + ElemSize * 4) || + CheckInvalidVLENandLMUL(TI, TheCall, SemaRef, Op2Type, + ElemSize * 4) || + CheckInvalidVLENandLMUL(TI, TheCall, SemaRef, Op3Type, ElemSize * 4); + } + + case RISCVVector::BI__builtin_rvv_sf_vc_i_se: + // bit_27_26, bit_24_20, bit_11_7, simm5, sew, log2lmul + return SemaRef.BuiltinConstantArgRange(TheCall, 0, 0, 3) || + SemaRef.BuiltinConstantArgRange(TheCall, 1, 0, 31) || + SemaRef.BuiltinConstantArgRange(TheCall, 2, 0, 31) || + SemaRef.BuiltinConstantArgRange(TheCall, 3, -16, 15) || + CheckLMUL(TheCall, 5); + case RISCVVector::BI__builtin_rvv_sf_vc_iv_se: + // bit_27_26, bit_11_7, vs2, simm5 + return SemaRef.BuiltinConstantArgRange(TheCall, 0, 0, 3) || + SemaRef.BuiltinConstantArgRange(TheCall, 1, 0, 31) || + SemaRef.BuiltinConstantArgRange(TheCall, 3, -16, 15); + case RISCVVector::BI__builtin_rvv_sf_vc_v_i: + case RISCVVector::BI__builtin_rvv_sf_vc_v_i_se: + // bit_27_26, bit_24_20, simm5 + return SemaRef.BuiltinConstantArgRange(TheCall, 0, 0, 3) || + SemaRef.BuiltinConstantArgRange(TheCall, 1, 0, 31) || + SemaRef.BuiltinConstantArgRange(TheCall, 2, -16, 15); + case RISCVVector::BI__builtin_rvv_sf_vc_v_iv: + case RISCVVector::BI__builtin_rvv_sf_vc_v_iv_se: + // bit_27_26, vs2, simm5 + return SemaRef.BuiltinConstantArgRange(TheCall, 0, 0, 3) || + SemaRef.BuiltinConstantArgRange(TheCall, 2, -16, 15); + case RISCVVector::BI__builtin_rvv_sf_vc_ivv_se: + case RISCVVector::BI__builtin_rvv_sf_vc_ivw_se: + case RISCVVector::BI__builtin_rvv_sf_vc_v_ivv: + case RISCVVector::BI__builtin_rvv_sf_vc_v_ivw: + case RISCVVector::BI__builtin_rvv_sf_vc_v_ivv_se: + case RISCVVector::BI__builtin_rvv_sf_vc_v_ivw_se: + // bit_27_26, vd, vs2, simm5 + return SemaRef.BuiltinConstantArgRange(TheCall, 0, 0, 3) || + SemaRef.BuiltinConstantArgRange(TheCall, 3, -16, 15); + case RISCVVector::BI__builtin_rvv_sf_vc_x_se: + // bit_27_26, bit_24_20, bit_11_7, xs1, sew, log2lmul + return SemaRef.BuiltinConstantArgRange(TheCall, 0, 0, 3) || + SemaRef.BuiltinConstantArgRange(TheCall, 1, 0, 31) || + SemaRef.BuiltinConstantArgRange(TheCall, 2, 0, 31) || + CheckLMUL(TheCall, 5); + case RISCVVector::BI__builtin_rvv_sf_vc_xv_se: + case RISCVVector::BI__builtin_rvv_sf_vc_vv_se: + // bit_27_26, bit_11_7, vs2, xs1/vs1 + case RISCVVector::BI__builtin_rvv_sf_vc_v_x: + case RISCVVector::BI__builtin_rvv_sf_vc_v_x_se: + // bit_27_26, bit_24-20, xs1 + return SemaRef.BuiltinConstantArgRange(TheCall, 0, 0, 3) || + SemaRef.BuiltinConstantArgRange(TheCall, 1, 0, 31); + case RISCVVector::BI__builtin_rvv_sf_vc_vvv_se: + case RISCVVector::BI__builtin_rvv_sf_vc_xvv_se: + case RISCVVector::BI__builtin_rvv_sf_vc_vvw_se: + case RISCVVector::BI__builtin_rvv_sf_vc_xvw_se: + // bit_27_26, vd, vs2, xs1 + case RISCVVector::BI__builtin_rvv_sf_vc_v_xv: + case RISCVVector::BI__builtin_rvv_sf_vc_v_vv: + case RISCVVector::BI__builtin_rvv_sf_vc_v_xv_se: + case RISCVVector::BI__builtin_rvv_sf_vc_v_vv_se: + // bit_27_26, vs2, xs1/vs1 + case RISCVVector::BI__builtin_rvv_sf_vc_v_xvv: + case RISCVVector::BI__builtin_rvv_sf_vc_v_vvv: + case RISCVVector::BI__builtin_rvv_sf_vc_v_xvw: + case RISCVVector::BI__builtin_rvv_sf_vc_v_vvw: + case RISCVVector::BI__builtin_rvv_sf_vc_v_xvv_se: + case RISCVVector::BI__builtin_rvv_sf_vc_v_vvv_se: + case RISCVVector::BI__builtin_rvv_sf_vc_v_xvw_se: + case RISCVVector::BI__builtin_rvv_sf_vc_v_vvw_se: + // bit_27_26, vd, vs2, xs1/vs1 + return SemaRef.BuiltinConstantArgRange(TheCall, 0, 0, 3); + case RISCVVector::BI__builtin_rvv_sf_vc_fv_se: + // bit_26, bit_11_7, vs2, fs1 + return SemaRef.BuiltinConstantArgRange(TheCall, 0, 0, 1) || + SemaRef.BuiltinConstantArgRange(TheCall, 1, 0, 31); + case RISCVVector::BI__builtin_rvv_sf_vc_fvv_se: + case RISCVVector::BI__builtin_rvv_sf_vc_fvw_se: + case RISCVVector::BI__builtin_rvv_sf_vc_v_fvv: + case RISCVVector::BI__builtin_rvv_sf_vc_v_fvw: + case RISCVVector::BI__builtin_rvv_sf_vc_v_fvv_se: + case RISCVVector::BI__builtin_rvv_sf_vc_v_fvw_se: + // bit_26, vd, vs2, fs1 + case RISCVVector::BI__builtin_rvv_sf_vc_v_fv: + case RISCVVector::BI__builtin_rvv_sf_vc_v_fv_se: + // bit_26, vs2, fs1 + return SemaRef.BuiltinConstantArgRange(TheCall, 0, 0, 1); + // Check if byteselect is in [0, 3] + case RISCV::BI__builtin_riscv_aes32dsi: + case RISCV::BI__builtin_riscv_aes32dsmi: + case RISCV::BI__builtin_riscv_aes32esi: + case RISCV::BI__builtin_riscv_aes32esmi: + case RISCV::BI__builtin_riscv_sm4ks: + case RISCV::BI__builtin_riscv_sm4ed: + return SemaRef.BuiltinConstantArgRange(TheCall, 2, 0, 3); + // Check if rnum is in [0, 10] + case RISCV::BI__builtin_riscv_aes64ks1i: + return SemaRef.BuiltinConstantArgRange(TheCall, 1, 0, 10); + // Check if value range for vxrm is in [0, 3] + case RISCVVector::BI__builtin_rvv_vaaddu_vv: + case RISCVVector::BI__builtin_rvv_vaaddu_vx: + case RISCVVector::BI__builtin_rvv_vaadd_vv: + case RISCVVector::BI__builtin_rvv_vaadd_vx: + case RISCVVector::BI__builtin_rvv_vasubu_vv: + case RISCVVector::BI__builtin_rvv_vasubu_vx: + case RISCVVector::BI__builtin_rvv_vasub_vv: + case RISCVVector::BI__builtin_rvv_vasub_vx: + case RISCVVector::BI__builtin_rvv_vsmul_vv: + case RISCVVector::BI__builtin_rvv_vsmul_vx: + case RISCVVector::BI__builtin_rvv_vssra_vv: + case RISCVVector::BI__builtin_rvv_vssra_vx: + case RISCVVector::BI__builtin_rvv_vssrl_vv: + case RISCVVector::BI__builtin_rvv_vssrl_vx: + case RISCVVector::BI__builtin_rvv_vnclip_wv: + case RISCVVector::BI__builtin_rvv_vnclip_wx: + case RISCVVector::BI__builtin_rvv_vnclipu_wv: + case RISCVVector::BI__builtin_rvv_vnclipu_wx: + return SemaRef.BuiltinConstantArgRange(TheCall, 2, 0, 3); + case RISCVVector::BI__builtin_rvv_vaaddu_vv_tu: + case RISCVVector::BI__builtin_rvv_vaaddu_vx_tu: + case RISCVVector::BI__builtin_rvv_vaadd_vv_tu: + case RISCVVector::BI__builtin_rvv_vaadd_vx_tu: + case RISCVVector::BI__builtin_rvv_vasubu_vv_tu: + case RISCVVector::BI__builtin_rvv_vasubu_vx_tu: + case RISCVVector::BI__builtin_rvv_vasub_vv_tu: + case RISCVVector::BI__builtin_rvv_vasub_vx_tu: + case RISCVVector::BI__builtin_rvv_vsmul_vv_tu: + case RISCVVector::BI__builtin_rvv_vsmul_vx_tu: + case RISCVVector::BI__builtin_rvv_vssra_vv_tu: + case RISCVVector::BI__builtin_rvv_vssra_vx_tu: + case RISCVVector::BI__builtin_rvv_vssrl_vv_tu: + case RISCVVector::BI__builtin_rvv_vssrl_vx_tu: + case RISCVVector::BI__builtin_rvv_vnclip_wv_tu: + case RISCVVector::BI__builtin_rvv_vnclip_wx_tu: + case RISCVVector::BI__builtin_rvv_vnclipu_wv_tu: + case RISCVVector::BI__builtin_rvv_vnclipu_wx_tu: + case RISCVVector::BI__builtin_rvv_vaaddu_vv_m: + case RISCVVector::BI__builtin_rvv_vaaddu_vx_m: + case RISCVVector::BI__builtin_rvv_vaadd_vv_m: + case RISCVVector::BI__builtin_rvv_vaadd_vx_m: + case RISCVVector::BI__builtin_rvv_vasubu_vv_m: + case RISCVVector::BI__builtin_rvv_vasubu_vx_m: + case RISCVVector::BI__builtin_rvv_vasub_vv_m: + case RISCVVector::BI__builtin_rvv_vasub_vx_m: + case RISCVVector::BI__builtin_rvv_vsmul_vv_m: + case RISCVVector::BI__builtin_rvv_vsmul_vx_m: + case RISCVVector::BI__builtin_rvv_vssra_vv_m: + case RISCVVector::BI__builtin_rvv_vssra_vx_m: + case RISCVVector::BI__builtin_rvv_vssrl_vv_m: + case RISCVVector::BI__builtin_rvv_vssrl_vx_m: + case RISCVVector::BI__builtin_rvv_vnclip_wv_m: + case RISCVVector::BI__builtin_rvv_vnclip_wx_m: + case RISCVVector::BI__builtin_rvv_vnclipu_wv_m: + case RISCVVector::BI__builtin_rvv_vnclipu_wx_m: + return SemaRef.BuiltinConstantArgRange(TheCall, 3, 0, 3); + case RISCVVector::BI__builtin_rvv_vaaddu_vv_tum: + case RISCVVector::BI__builtin_rvv_vaaddu_vv_tumu: + case RISCVVector::BI__builtin_rvv_vaaddu_vv_mu: + case RISCVVector::BI__builtin_rvv_vaaddu_vx_tum: + case RISCVVector::BI__builtin_rvv_vaaddu_vx_tumu: + case RISCVVector::BI__builtin_rvv_vaaddu_vx_mu: + case RISCVVector::BI__builtin_rvv_vaadd_vv_tum: + case RISCVVector::BI__builtin_rvv_vaadd_vv_tumu: + case RISCVVector::BI__builtin_rvv_vaadd_vv_mu: + case RISCVVector::BI__builtin_rvv_vaadd_vx_tum: + case RISCVVector::BI__builtin_rvv_vaadd_vx_tumu: + case RISCVVector::BI__builtin_rvv_vaadd_vx_mu: + case RISCVVector::BI__builtin_rvv_vasubu_vv_tum: + case RISCVVector::BI__builtin_rvv_vasubu_vv_tumu: + case RISCVVector::BI__builtin_rvv_vasubu_vv_mu: + case RISCVVector::BI__builtin_rvv_vasubu_vx_tum: + case RISCVVector::BI__builtin_rvv_vasubu_vx_tumu: + case RISCVVector::BI__builtin_rvv_vasubu_vx_mu: + case RISCVVector::BI__builtin_rvv_vasub_vv_tum: + case RISCVVector::BI__builtin_rvv_vasub_vv_tumu: + case RISCVVector::BI__builtin_rvv_vasub_vv_mu: + case RISCVVector::BI__builtin_rvv_vasub_vx_tum: + case RISCVVector::BI__builtin_rvv_vasub_vx_tumu: + case RISCVVector::BI__builtin_rvv_vasub_vx_mu: + case RISCVVector::BI__builtin_rvv_vsmul_vv_mu: + case RISCVVector::BI__builtin_rvv_vsmul_vx_mu: + case RISCVVector::BI__builtin_rvv_vssra_vv_mu: + case RISCVVector::BI__builtin_rvv_vssra_vx_mu: + case RISCVVector::BI__builtin_rvv_vssrl_vv_mu: + case RISCVVector::BI__builtin_rvv_vssrl_vx_mu: + case RISCVVector::BI__builtin_rvv_vnclip_wv_mu: + case RISCVVector::BI__builtin_rvv_vnclip_wx_mu: + case RISCVVector::BI__builtin_rvv_vnclipu_wv_mu: + case RISCVVector::BI__builtin_rvv_vnclipu_wx_mu: + case RISCVVector::BI__builtin_rvv_vsmul_vv_tum: + case RISCVVector::BI__builtin_rvv_vsmul_vx_tum: + case RISCVVector::BI__builtin_rvv_vssra_vv_tum: + case RISCVVector::BI__builtin_rvv_vssra_vx_tum: + case RISCVVector::BI__builtin_rvv_vssrl_vv_tum: + case RISCVVector::BI__builtin_rvv_vssrl_vx_tum: + case RISCVVector::BI__builtin_rvv_vnclip_wv_tum: + case RISCVVector::BI__builtin_rvv_vnclip_wx_tum: + case RISCVVector::BI__builtin_rvv_vnclipu_wv_tum: + case RISCVVector::BI__builtin_rvv_vnclipu_wx_tum: + case RISCVVector::BI__builtin_rvv_vsmul_vv_tumu: + case RISCVVector::BI__builtin_rvv_vsmul_vx_tumu: + case RISCVVector::BI__builtin_rvv_vssra_vv_tumu: + case RISCVVector::BI__builtin_rvv_vssra_vx_tumu: + case RISCVVector::BI__builtin_rvv_vssrl_vv_tumu: + case RISCVVector::BI__builtin_rvv_vssrl_vx_tumu: + case RISCVVector::BI__builtin_rvv_vnclip_wv_tumu: + case RISCVVector::BI__builtin_rvv_vnclip_wx_tumu: + case RISCVVector::BI__builtin_rvv_vnclipu_wv_tumu: + case RISCVVector::BI__builtin_rvv_vnclipu_wx_tumu: + return SemaRef.BuiltinConstantArgRange(TheCall, 4, 0, 3); + case RISCVVector::BI__builtin_rvv_vfsqrt_v_rm: + case RISCVVector::BI__builtin_rvv_vfrec7_v_rm: + case RISCVVector::BI__builtin_rvv_vfcvt_x_f_v_rm: + case RISCVVector::BI__builtin_rvv_vfcvt_xu_f_v_rm: + case RISCVVector::BI__builtin_rvv_vfcvt_f_x_v_rm: + case RISCVVector::BI__builtin_rvv_vfcvt_f_xu_v_rm: + case RISCVVector::BI__builtin_rvv_vfwcvt_x_f_v_rm: + case RISCVVector::BI__builtin_rvv_vfwcvt_xu_f_v_rm: + case RISCVVector::BI__builtin_rvv_vfncvt_x_f_w_rm: + case RISCVVector::BI__builtin_rvv_vfncvt_xu_f_w_rm: + case RISCVVector::BI__builtin_rvv_vfncvt_f_x_w_rm: + case RISCVVector::BI__builtin_rvv_vfncvt_f_xu_w_rm: + case RISCVVector::BI__builtin_rvv_vfncvt_f_f_w_rm: + return SemaRef.BuiltinConstantArgRange(TheCall, 1, 0, 4); + case RISCVVector::BI__builtin_rvv_vfadd_vv_rm: + case RISCVVector::BI__builtin_rvv_vfadd_vf_rm: + case RISCVVector::BI__builtin_rvv_vfsub_vv_rm: + case RISCVVector::BI__builtin_rvv_vfsub_vf_rm: + case RISCVVector::BI__builtin_rvv_vfrsub_vf_rm: + case RISCVVector::BI__builtin_rvv_vfwadd_vv_rm: + case RISCVVector::BI__builtin_rvv_vfwadd_vf_rm: + case RISCVVector::BI__builtin_rvv_vfwsub_vv_rm: + case RISCVVector::BI__builtin_rvv_vfwsub_vf_rm: + case RISCVVector::BI__builtin_rvv_vfwadd_wv_rm: + case RISCVVector::BI__builtin_rvv_vfwadd_wf_rm: + case RISCVVector::BI__builtin_rvv_vfwsub_wv_rm: + case RISCVVector::BI__builtin_rvv_vfwsub_wf_rm: + case RISCVVector::BI__builtin_rvv_vfmul_vv_rm: + case RISCVVector::BI__builtin_rvv_vfmul_vf_rm: + case RISCVVector::BI__builtin_rvv_vfdiv_vv_rm: + case RISCVVector::BI__builtin_rvv_vfdiv_vf_rm: + case RISCVVector::BI__builtin_rvv_vfrdiv_vf_rm: + case RISCVVector::BI__builtin_rvv_vfwmul_vv_rm: + case RISCVVector::BI__builtin_rvv_vfwmul_vf_rm: + case RISCVVector::BI__builtin_rvv_vfredosum_vs_rm: + case RISCVVector::BI__builtin_rvv_vfredusum_vs_rm: + case RISCVVector::BI__builtin_rvv_vfwredosum_vs_rm: + case RISCVVector::BI__builtin_rvv_vfwredusum_vs_rm: + case RISCVVector::BI__builtin_rvv_vfsqrt_v_rm_tu: + case RISCVVector::BI__builtin_rvv_vfrec7_v_rm_tu: + case RISCVVector::BI__builtin_rvv_vfcvt_x_f_v_rm_tu: + case RISCVVector::BI__builtin_rvv_vfcvt_xu_f_v_rm_tu: + case RISCVVector::BI__builtin_rvv_vfcvt_f_x_v_rm_tu: + case RISCVVector::BI__builtin_rvv_vfcvt_f_xu_v_rm_tu: + case RISCVVector::BI__builtin_rvv_vfwcvt_x_f_v_rm_tu: + case RISCVVector::BI__builtin_rvv_vfwcvt_xu_f_v_rm_tu: + case RISCVVector::BI__builtin_rvv_vfncvt_x_f_w_rm_tu: + case RISCVVector::BI__builtin_rvv_vfncvt_xu_f_w_rm_tu: + case RISCVVector::BI__builtin_rvv_vfncvt_f_x_w_rm_tu: + case RISCVVector::BI__builtin_rvv_vfncvt_f_xu_w_rm_tu: + case RISCVVector::BI__builtin_rvv_vfncvt_f_f_w_rm_tu: + case RISCVVector::BI__builtin_rvv_vfsqrt_v_rm_m: + case RISCVVector::BI__builtin_rvv_vfrec7_v_rm_m: + case RISCVVector::BI__builtin_rvv_vfcvt_x_f_v_rm_m: + case RISCVVector::BI__builtin_rvv_vfcvt_xu_f_v_rm_m: + case RISCVVector::BI__builtin_rvv_vfcvt_f_x_v_rm_m: + case RISCVVector::BI__builtin_rvv_vfcvt_f_xu_v_rm_m: + case RISCVVector::BI__builtin_rvv_vfwcvt_x_f_v_rm_m: + case RISCVVector::BI__builtin_rvv_vfwcvt_xu_f_v_rm_m: + case RISCVVector::BI__builtin_rvv_vfncvt_x_f_w_rm_m: + case RISCVVector::BI__builtin_rvv_vfncvt_xu_f_w_rm_m: + case RISCVVector::BI__builtin_rvv_vfncvt_f_x_w_rm_m: + case RISCVVector::BI__builtin_rvv_vfncvt_f_xu_w_rm_m: + case RISCVVector::BI__builtin_rvv_vfncvt_f_f_w_rm_m: + return SemaRef.BuiltinConstantArgRange(TheCall, 2, 0, 4); + case RISCVVector::BI__builtin_rvv_vfadd_vv_rm_tu: + case RISCVVector::BI__builtin_rvv_vfadd_vf_rm_tu: + case RISCVVector::BI__builtin_rvv_vfsub_vv_rm_tu: + case RISCVVector::BI__builtin_rvv_vfsub_vf_rm_tu: + case RISCVVector::BI__builtin_rvv_vfrsub_vf_rm_tu: + case RISCVVector::BI__builtin_rvv_vfwadd_vv_rm_tu: + case RISCVVector::BI__builtin_rvv_vfwadd_vf_rm_tu: + case RISCVVector::BI__builtin_rvv_vfwsub_vv_rm_tu: + case RISCVVector::BI__builtin_rvv_vfwsub_vf_rm_tu: + case RISCVVector::BI__builtin_rvv_vfwadd_wv_rm_tu: + case RISCVVector::BI__builtin_rvv_vfwadd_wf_rm_tu: + case RISCVVector::BI__builtin_rvv_vfwsub_wv_rm_tu: + case RISCVVector::BI__builtin_rvv_vfwsub_wf_rm_tu: + case RISCVVector::BI__builtin_rvv_vfmul_vv_rm_tu: + case RISCVVector::BI__builtin_rvv_vfmul_vf_rm_tu: + case RISCVVector::BI__builtin_rvv_vfdiv_vv_rm_tu: + case RISCVVector::BI__builtin_rvv_vfdiv_vf_rm_tu: + case RISCVVector::BI__builtin_rvv_vfrdiv_vf_rm_tu: + case RISCVVector::BI__builtin_rvv_vfwmul_vv_rm_tu: + case RISCVVector::BI__builtin_rvv_vfwmul_vf_rm_tu: + case RISCVVector::BI__builtin_rvv_vfredosum_vs_rm_tu: + case RISCVVector::BI__builtin_rvv_vfredusum_vs_rm_tu: + case RISCVVector::BI__builtin_rvv_vfwredosum_vs_rm_tu: + case RISCVVector::BI__builtin_rvv_vfwredusum_vs_rm_tu: + case RISCVVector::BI__builtin_rvv_vfmacc_vv_rm: + case RISCVVector::BI__builtin_rvv_vfmacc_vf_rm: + case RISCVVector::BI__builtin_rvv_vfnmacc_vv_rm: + case RISCVVector::BI__builtin_rvv_vfnmacc_vf_rm: + case RISCVVector::BI__builtin_rvv_vfmsac_vv_rm: + case RISCVVector::BI__builtin_rvv_vfmsac_vf_rm: + case RISCVVector::BI__builtin_rvv_vfnmsac_vv_rm: + case RISCVVector::BI__builtin_rvv_vfnmsac_vf_rm: + case RISCVVector::BI__builtin_rvv_vfmadd_vv_rm: + case RISCVVector::BI__builtin_rvv_vfmadd_vf_rm: + case RISCVVector::BI__builtin_rvv_vfnmadd_vv_rm: + case RISCVVector::BI__builtin_rvv_vfnmadd_vf_rm: + case RISCVVector::BI__builtin_rvv_vfmsub_vv_rm: + case RISCVVector::BI__builtin_rvv_vfmsub_vf_rm: + case RISCVVector::BI__builtin_rvv_vfnmsub_vv_rm: + case RISCVVector::BI__builtin_rvv_vfnmsub_vf_rm: + case RISCVVector::BI__builtin_rvv_vfwmacc_vv_rm: + case RISCVVector::BI__builtin_rvv_vfwmacc_vf_rm: + case RISCVVector::BI__builtin_rvv_vfwnmacc_vv_rm: + case RISCVVector::BI__builtin_rvv_vfwnmacc_vf_rm: + case RISCVVector::BI__builtin_rvv_vfwmsac_vv_rm: + case RISCVVector::BI__builtin_rvv_vfwmsac_vf_rm: + case RISCVVector::BI__builtin_rvv_vfwnmsac_vv_rm: + case RISCVVector::BI__builtin_rvv_vfwnmsac_vf_rm: + case RISCVVector::BI__builtin_rvv_vfmacc_vv_rm_tu: + case RISCVVector::BI__builtin_rvv_vfmacc_vf_rm_tu: + case RISCVVector::BI__builtin_rvv_vfnmacc_vv_rm_tu: + case RISCVVector::BI__builtin_rvv_vfnmacc_vf_rm_tu: + case RISCVVector::BI__builtin_rvv_vfmsac_vv_rm_tu: + case RISCVVector::BI__builtin_rvv_vfmsac_vf_rm_tu: + case RISCVVector::BI__builtin_rvv_vfnmsac_vv_rm_tu: + case RISCVVector::BI__builtin_rvv_vfnmsac_vf_rm_tu: + case RISCVVector::BI__builtin_rvv_vfmadd_vv_rm_tu: + case RISCVVector::BI__builtin_rvv_vfmadd_vf_rm_tu: + case RISCVVector::BI__builtin_rvv_vfnmadd_vv_rm_tu: + case RISCVVector::BI__builtin_rvv_vfnmadd_vf_rm_tu: + case RISCVVector::BI__builtin_rvv_vfmsub_vv_rm_tu: + case RISCVVector::BI__builtin_rvv_vfmsub_vf_rm_tu: + case RISCVVector::BI__builtin_rvv_vfnmsub_vv_rm_tu: + case RISCVVector::BI__builtin_rvv_vfnmsub_vf_rm_tu: + case RISCVVector::BI__builtin_rvv_vfwmacc_vv_rm_tu: + case RISCVVector::BI__builtin_rvv_vfwmacc_vf_rm_tu: + case RISCVVector::BI__builtin_rvv_vfwnmacc_vv_rm_tu: + case RISCVVector::BI__builtin_rvv_vfwnmacc_vf_rm_tu: + case RISCVVector::BI__builtin_rvv_vfwmsac_vv_rm_tu: + case RISCVVector::BI__builtin_rvv_vfwmsac_vf_rm_tu: + case RISCVVector::BI__builtin_rvv_vfwnmsac_vv_rm_tu: + case RISCVVector::BI__builtin_rvv_vfwnmsac_vf_rm_tu: + case RISCVVector::BI__builtin_rvv_vfadd_vv_rm_m: + case RISCVVector::BI__builtin_rvv_vfadd_vf_rm_m: + case RISCVVector::BI__builtin_rvv_vfsub_vv_rm_m: + case RISCVVector::BI__builtin_rvv_vfsub_vf_rm_m: + case RISCVVector::BI__builtin_rvv_vfrsub_vf_rm_m: + case RISCVVector::BI__builtin_rvv_vfwadd_vv_rm_m: + case RISCVVector::BI__builtin_rvv_vfwadd_vf_rm_m: + case RISCVVector::BI__builtin_rvv_vfwsub_vv_rm_m: + case RISCVVector::BI__builtin_rvv_vfwsub_vf_rm_m: + case RISCVVector::BI__builtin_rvv_vfwadd_wv_rm_m: + case RISCVVector::BI__builtin_rvv_vfwadd_wf_rm_m: + case RISCVVector::BI__builtin_rvv_vfwsub_wv_rm_m: + case RISCVVector::BI__builtin_rvv_vfwsub_wf_rm_m: + case RISCVVector::BI__builtin_rvv_vfmul_vv_rm_m: + case RISCVVector::BI__builtin_rvv_vfmul_vf_rm_m: + case RISCVVector::BI__builtin_rvv_vfdiv_vv_rm_m: + case RISCVVector::BI__builtin_rvv_vfdiv_vf_rm_m: + case RISCVVector::BI__builtin_rvv_vfrdiv_vf_rm_m: + case RISCVVector::BI__builtin_rvv_vfwmul_vv_rm_m: + case RISCVVector::BI__builtin_rvv_vfwmul_vf_rm_m: + case RISCVVector::BI__builtin_rvv_vfredosum_vs_rm_m: + case RISCVVector::BI__builtin_rvv_vfredusum_vs_rm_m: + case RISCVVector::BI__builtin_rvv_vfwredosum_vs_rm_m: + case RISCVVector::BI__builtin_rvv_vfwredusum_vs_rm_m: + case RISCVVector::BI__builtin_rvv_vfsqrt_v_rm_tum: + case RISCVVector::BI__builtin_rvv_vfrec7_v_rm_tum: + case RISCVVector::BI__builtin_rvv_vfcvt_x_f_v_rm_tum: + case RISCVVector::BI__builtin_rvv_vfcvt_xu_f_v_rm_tum: + case RISCVVector::BI__builtin_rvv_vfcvt_f_x_v_rm_tum: + case RISCVVector::BI__builtin_rvv_vfcvt_f_xu_v_rm_tum: + case RISCVVector::BI__builtin_rvv_vfwcvt_x_f_v_rm_tum: + case RISCVVector::BI__builtin_rvv_vfwcvt_xu_f_v_rm_tum: + case RISCVVector::BI__builtin_rvv_vfncvt_x_f_w_rm_tum: + case RISCVVector::BI__builtin_rvv_vfncvt_xu_f_w_rm_tum: + case RISCVVector::BI__builtin_rvv_vfncvt_f_x_w_rm_tum: + case RISCVVector::BI__builtin_rvv_vfncvt_f_xu_w_rm_tum: + case RISCVVector::BI__builtin_rvv_vfncvt_f_f_w_rm_tum: + case RISCVVector::BI__builtin_rvv_vfsqrt_v_rm_tumu: + case RISCVVector::BI__builtin_rvv_vfrec7_v_rm_tumu: + case RISCVVector::BI__builtin_rvv_vfcvt_x_f_v_rm_tumu: + case RISCVVector::BI__builtin_rvv_vfcvt_xu_f_v_rm_tumu: + case RISCVVector::BI__builtin_rvv_vfcvt_f_x_v_rm_tumu: + case RISCVVector::BI__builtin_rvv_vfcvt_f_xu_v_rm_tumu: + case RISCVVector::BI__builtin_rvv_vfwcvt_x_f_v_rm_tumu: + case RISCVVector::BI__builtin_rvv_vfwcvt_xu_f_v_rm_tumu: + case RISCVVector::BI__builtin_rvv_vfncvt_x_f_w_rm_tumu: + case RISCVVector::BI__builtin_rvv_vfncvt_xu_f_w_rm_tumu: + case RISCVVector::BI__builtin_rvv_vfncvt_f_x_w_rm_tumu: + case RISCVVector::BI__builtin_rvv_vfncvt_f_xu_w_rm_tumu: + case RISCVVector::BI__builtin_rvv_vfncvt_f_f_w_rm_tumu: + case RISCVVector::BI__builtin_rvv_vfsqrt_v_rm_mu: + case RISCVVector::BI__builtin_rvv_vfrec7_v_rm_mu: + case RISCVVector::BI__builtin_rvv_vfcvt_x_f_v_rm_mu: + case RISCVVector::BI__builtin_rvv_vfcvt_xu_f_v_rm_mu: + case RISCVVector::BI__builtin_rvv_vfcvt_f_x_v_rm_mu: + case RISCVVector::BI__builtin_rvv_vfcvt_f_xu_v_rm_mu: + case RISCVVector::BI__builtin_rvv_vfwcvt_x_f_v_rm_mu: + case RISCVVector::BI__builtin_rvv_vfwcvt_xu_f_v_rm_mu: + case RISCVVector::BI__builtin_rvv_vfncvt_x_f_w_rm_mu: + case RISCVVector::BI__builtin_rvv_vfncvt_xu_f_w_rm_mu: + case RISCVVector::BI__builtin_rvv_vfncvt_f_x_w_rm_mu: + case RISCVVector::BI__builtin_rvv_vfncvt_f_xu_w_rm_mu: + case RISCVVector::BI__builtin_rvv_vfncvt_f_f_w_rm_mu: + return SemaRef.BuiltinConstantArgRange(TheCall, 3, 0, 4); + case RISCVVector::BI__builtin_rvv_vfmacc_vv_rm_m: + case RISCVVector::BI__builtin_rvv_vfmacc_vf_rm_m: + case RISCVVector::BI__builtin_rvv_vfnmacc_vv_rm_m: + case RISCVVector::BI__builtin_rvv_vfnmacc_vf_rm_m: + case RISCVVector::BI__builtin_rvv_vfmsac_vv_rm_m: + case RISCVVector::BI__builtin_rvv_vfmsac_vf_rm_m: + case RISCVVector::BI__builtin_rvv_vfnmsac_vv_rm_m: + case RISCVVector::BI__builtin_rvv_vfnmsac_vf_rm_m: + case RISCVVector::BI__builtin_rvv_vfmadd_vv_rm_m: + case RISCVVector::BI__builtin_rvv_vfmadd_vf_rm_m: + case RISCVVector::BI__builtin_rvv_vfnmadd_vv_rm_m: + case RISCVVector::BI__builtin_rvv_vfnmadd_vf_rm_m: + case RISCVVector::BI__builtin_rvv_vfmsub_vv_rm_m: + case RISCVVector::BI__builtin_rvv_vfmsub_vf_rm_m: + case RISCVVector::BI__builtin_rvv_vfnmsub_vv_rm_m: + case RISCVVector::BI__builtin_rvv_vfnmsub_vf_rm_m: + case RISCVVector::BI__builtin_rvv_vfwmacc_vv_rm_m: + case RISCVVector::BI__builtin_rvv_vfwmacc_vf_rm_m: + case RISCVVector::BI__builtin_rvv_vfwnmacc_vv_rm_m: + case RISCVVector::BI__builtin_rvv_vfwnmacc_vf_rm_m: + case RISCVVector::BI__builtin_rvv_vfwmsac_vv_rm_m: + case RISCVVector::BI__builtin_rvv_vfwmsac_vf_rm_m: + case RISCVVector::BI__builtin_rvv_vfwnmsac_vv_rm_m: + case RISCVVector::BI__builtin_rvv_vfwnmsac_vf_rm_m: + case RISCVVector::BI__builtin_rvv_vfadd_vv_rm_tum: + case RISCVVector::BI__builtin_rvv_vfadd_vf_rm_tum: + case RISCVVector::BI__builtin_rvv_vfsub_vv_rm_tum: + case RISCVVector::BI__builtin_rvv_vfsub_vf_rm_tum: + case RISCVVector::BI__builtin_rvv_vfrsub_vf_rm_tum: + case RISCVVector::BI__builtin_rvv_vfwadd_vv_rm_tum: + case RISCVVector::BI__builtin_rvv_vfwadd_vf_rm_tum: + case RISCVVector::BI__builtin_rvv_vfwsub_vv_rm_tum: + case RISCVVector::BI__builtin_rvv_vfwsub_vf_rm_tum: + case RISCVVector::BI__builtin_rvv_vfwadd_wv_rm_tum: + case RISCVVector::BI__builtin_rvv_vfwadd_wf_rm_tum: + case RISCVVector::BI__builtin_rvv_vfwsub_wv_rm_tum: + case RISCVVector::BI__builtin_rvv_vfwsub_wf_rm_tum: + case RISCVVector::BI__builtin_rvv_vfmul_vv_rm_tum: + case RISCVVector::BI__builtin_rvv_vfmul_vf_rm_tum: + case RISCVVector::BI__builtin_rvv_vfdiv_vv_rm_tum: + case RISCVVector::BI__builtin_rvv_vfdiv_vf_rm_tum: + case RISCVVector::BI__builtin_rvv_vfrdiv_vf_rm_tum: + case RISCVVector::BI__builtin_rvv_vfwmul_vv_rm_tum: + case RISCVVector::BI__builtin_rvv_vfwmul_vf_rm_tum: + case RISCVVector::BI__builtin_rvv_vfmacc_vv_rm_tum: + case RISCVVector::BI__builtin_rvv_vfmacc_vf_rm_tum: + case RISCVVector::BI__builtin_rvv_vfnmacc_vv_rm_tum: + case RISCVVector::BI__builtin_rvv_vfnmacc_vf_rm_tum: + case RISCVVector::BI__builtin_rvv_vfmsac_vv_rm_tum: + case RISCVVector::BI__builtin_rvv_vfmsac_vf_rm_tum: + case RISCVVector::BI__builtin_rvv_vfnmsac_vv_rm_tum: + case RISCVVector::BI__builtin_rvv_vfnmsac_vf_rm_tum: + case RISCVVector::BI__builtin_rvv_vfmadd_vv_rm_tum: + case RISCVVector::BI__builtin_rvv_vfmadd_vf_rm_tum: + case RISCVVector::BI__builtin_rvv_vfnmadd_vv_rm_tum: + case RISCVVector::BI__builtin_rvv_vfnmadd_vf_rm_tum: + case RISCVVector::BI__builtin_rvv_vfmsub_vv_rm_tum: + case RISCVVector::BI__builtin_rvv_vfmsub_vf_rm_tum: + case RISCVVector::BI__builtin_rvv_vfnmsub_vv_rm_tum: + case RISCVVector::BI__builtin_rvv_vfnmsub_vf_rm_tum: + case RISCVVector::BI__builtin_rvv_vfwmacc_vv_rm_tum: + case RISCVVector::BI__builtin_rvv_vfwmacc_vf_rm_tum: + case RISCVVector::BI__builtin_rvv_vfwnmacc_vv_rm_tum: + case RISCVVector::BI__builtin_rvv_vfwnmacc_vf_rm_tum: + case RISCVVector::BI__builtin_rvv_vfwmsac_vv_rm_tum: + case RISCVVector::BI__builtin_rvv_vfwmsac_vf_rm_tum: + case RISCVVector::BI__builtin_rvv_vfwnmsac_vv_rm_tum: + case RISCVVector::BI__builtin_rvv_vfwnmsac_vf_rm_tum: + case RISCVVector::BI__builtin_rvv_vfredosum_vs_rm_tum: + case RISCVVector::BI__builtin_rvv_vfredusum_vs_rm_tum: + case RISCVVector::BI__builtin_rvv_vfwredosum_vs_rm_tum: + case RISCVVector::BI__builtin_rvv_vfwredusum_vs_rm_tum: + case RISCVVector::BI__builtin_rvv_vfadd_vv_rm_tumu: + case RISCVVector::BI__builtin_rvv_vfadd_vf_rm_tumu: + case RISCVVector::BI__builtin_rvv_vfsub_vv_rm_tumu: + case RISCVVector::BI__builtin_rvv_vfsub_vf_rm_tumu: + case RISCVVector::BI__builtin_rvv_vfrsub_vf_rm_tumu: + case RISCVVector::BI__builtin_rvv_vfwadd_vv_rm_tumu: + case RISCVVector::BI__builtin_rvv_vfwadd_vf_rm_tumu: + case RISCVVector::BI__builtin_rvv_vfwsub_vv_rm_tumu: + case RISCVVector::BI__builtin_rvv_vfwsub_vf_rm_tumu: + case RISCVVector::BI__builtin_rvv_vfwadd_wv_rm_tumu: + case RISCVVector::BI__builtin_rvv_vfwadd_wf_rm_tumu: + case RISCVVector::BI__builtin_rvv_vfwsub_wv_rm_tumu: + case RISCVVector::BI__builtin_rvv_vfwsub_wf_rm_tumu: + case RISCVVector::BI__builtin_rvv_vfmul_vv_rm_tumu: + case RISCVVector::BI__builtin_rvv_vfmul_vf_rm_tumu: + case RISCVVector::BI__builtin_rvv_vfdiv_vv_rm_tumu: + case RISCVVector::BI__builtin_rvv_vfdiv_vf_rm_tumu: + case RISCVVector::BI__builtin_rvv_vfrdiv_vf_rm_tumu: + case RISCVVector::BI__builtin_rvv_vfwmul_vv_rm_tumu: + case RISCVVector::BI__builtin_rvv_vfwmul_vf_rm_tumu: + case RISCVVector::BI__builtin_rvv_vfmacc_vv_rm_tumu: + case RISCVVector::BI__builtin_rvv_vfmacc_vf_rm_tumu: + case RISCVVector::BI__builtin_rvv_vfnmacc_vv_rm_tumu: + case RISCVVector::BI__builtin_rvv_vfnmacc_vf_rm_tumu: + case RISCVVector::BI__builtin_rvv_vfmsac_vv_rm_tumu: + case RISCVVector::BI__builtin_rvv_vfmsac_vf_rm_tumu: + case RISCVVector::BI__builtin_rvv_vfnmsac_vv_rm_tumu: + case RISCVVector::BI__builtin_rvv_vfnmsac_vf_rm_tumu: + case RISCVVector::BI__builtin_rvv_vfmadd_vv_rm_tumu: + case RISCVVector::BI__builtin_rvv_vfmadd_vf_rm_tumu: + case RISCVVector::BI__builtin_rvv_vfnmadd_vv_rm_tumu: + case RISCVVector::BI__builtin_rvv_vfnmadd_vf_rm_tumu: + case RISCVVector::BI__builtin_rvv_vfmsub_vv_rm_tumu: + case RISCVVector::BI__builtin_rvv_vfmsub_vf_rm_tumu: + case RISCVVector::BI__builtin_rvv_vfnmsub_vv_rm_tumu: + case RISCVVector::BI__builtin_rvv_vfnmsub_vf_rm_tumu: + case RISCVVector::BI__builtin_rvv_vfwmacc_vv_rm_tumu: + case RISCVVector::BI__builtin_rvv_vfwmacc_vf_rm_tumu: + case RISCVVector::BI__builtin_rvv_vfwnmacc_vv_rm_tumu: + case RISCVVector::BI__builtin_rvv_vfwnmacc_vf_rm_tumu: + case RISCVVector::BI__builtin_rvv_vfwmsac_vv_rm_tumu: + case RISCVVector::BI__builtin_rvv_vfwmsac_vf_rm_tumu: + case RISCVVector::BI__builtin_rvv_vfwnmsac_vv_rm_tumu: + case RISCVVector::BI__builtin_rvv_vfwnmsac_vf_rm_tumu: + case RISCVVector::BI__builtin_rvv_vfadd_vv_rm_mu: + case RISCVVector::BI__builtin_rvv_vfadd_vf_rm_mu: + case RISCVVector::BI__builtin_rvv_vfsub_vv_rm_mu: + case RISCVVector::BI__builtin_rvv_vfsub_vf_rm_mu: + case RISCVVector::BI__builtin_rvv_vfrsub_vf_rm_mu: + case RISCVVector::BI__builtin_rvv_vfwadd_vv_rm_mu: + case RISCVVector::BI__builtin_rvv_vfwadd_vf_rm_mu: + case RISCVVector::BI__builtin_rvv_vfwsub_vv_rm_mu: + case RISCVVector::BI__builtin_rvv_vfwsub_vf_rm_mu: + case RISCVVector::BI__builtin_rvv_vfwadd_wv_rm_mu: + case RISCVVector::BI__builtin_rvv_vfwadd_wf_rm_mu: + case RISCVVector::BI__builtin_rvv_vfwsub_wv_rm_mu: + case RISCVVector::BI__builtin_rvv_vfwsub_wf_rm_mu: + case RISCVVector::BI__builtin_rvv_vfmul_vv_rm_mu: + case RISCVVector::BI__builtin_rvv_vfmul_vf_rm_mu: + case RISCVVector::BI__builtin_rvv_vfdiv_vv_rm_mu: + case RISCVVector::BI__builtin_rvv_vfdiv_vf_rm_mu: + case RISCVVector::BI__builtin_rvv_vfrdiv_vf_rm_mu: + case RISCVVector::BI__builtin_rvv_vfwmul_vv_rm_mu: + case RISCVVector::BI__builtin_rvv_vfwmul_vf_rm_mu: + case RISCVVector::BI__builtin_rvv_vfmacc_vv_rm_mu: + case RISCVVector::BI__builtin_rvv_vfmacc_vf_rm_mu: + case RISCVVector::BI__builtin_rvv_vfnmacc_vv_rm_mu: + case RISCVVector::BI__builtin_rvv_vfnmacc_vf_rm_mu: + case RISCVVector::BI__builtin_rvv_vfmsac_vv_rm_mu: + case RISCVVector::BI__builtin_rvv_vfmsac_vf_rm_mu: + case RISCVVector::BI__builtin_rvv_vfnmsac_vv_rm_mu: + case RISCVVector::BI__builtin_rvv_vfnmsac_vf_rm_mu: + case RISCVVector::BI__builtin_rvv_vfmadd_vv_rm_mu: + case RISCVVector::BI__builtin_rvv_vfmadd_vf_rm_mu: + case RISCVVector::BI__builtin_rvv_vfnmadd_vv_rm_mu: + case RISCVVector::BI__builtin_rvv_vfnmadd_vf_rm_mu: + case RISCVVector::BI__builtin_rvv_vfmsub_vv_rm_mu: + case RISCVVector::BI__builtin_rvv_vfmsub_vf_rm_mu: + case RISCVVector::BI__builtin_rvv_vfnmsub_vv_rm_mu: + case RISCVVector::BI__builtin_rvv_vfnmsub_vf_rm_mu: + case RISCVVector::BI__builtin_rvv_vfwmacc_vv_rm_mu: + case RISCVVector::BI__builtin_rvv_vfwmacc_vf_rm_mu: + case RISCVVector::BI__builtin_rvv_vfwnmacc_vv_rm_mu: + case RISCVVector::BI__builtin_rvv_vfwnmacc_vf_rm_mu: + case RISCVVector::BI__builtin_rvv_vfwmsac_vv_rm_mu: + case RISCVVector::BI__builtin_rvv_vfwmsac_vf_rm_mu: + case RISCVVector::BI__builtin_rvv_vfwnmsac_vv_rm_mu: + case RISCVVector::BI__builtin_rvv_vfwnmsac_vf_rm_mu: + return SemaRef.BuiltinConstantArgRange(TheCall, 4, 0, 4); + case RISCV::BI__builtin_riscv_ntl_load: + case RISCV::BI__builtin_riscv_ntl_store: + DeclRefExpr *DRE = + cast(TheCall->getCallee()->IgnoreParenCasts()); + assert((BuiltinID == RISCV::BI__builtin_riscv_ntl_store || + BuiltinID == RISCV::BI__builtin_riscv_ntl_load) && + "Unexpected RISC-V nontemporal load/store builtin!"); + bool IsStore = BuiltinID == RISCV::BI__builtin_riscv_ntl_store; + unsigned NumArgs = IsStore ? 3 : 2; + + if (SemaRef.checkArgCountAtLeast(TheCall, NumArgs - 1)) + return true; + + if (SemaRef.checkArgCountAtMost(TheCall, NumArgs)) + return true; + + // Domain value should be compile-time constant. + // 2 <= domain <= 5 + if (TheCall->getNumArgs() == NumArgs && + SemaRef.BuiltinConstantArgRange(TheCall, NumArgs - 1, 2, 5)) + return true; + + Expr *PointerArg = TheCall->getArg(0); + ExprResult PointerArgResult = + SemaRef.DefaultFunctionArrayLvalueConversion(PointerArg); + + if (PointerArgResult.isInvalid()) + return true; + PointerArg = PointerArgResult.get(); + + const PointerType *PtrType = PointerArg->getType()->getAs(); + if (!PtrType) { + Diag(DRE->getBeginLoc(), diag::err_nontemporal_builtin_must_be_pointer) + << PointerArg->getType() << PointerArg->getSourceRange(); + return true; + } + + QualType ValType = PtrType->getPointeeType(); + ValType = ValType.getUnqualifiedType(); + if (!ValType->isIntegerType() && !ValType->isAnyPointerType() && + !ValType->isBlockPointerType() && !ValType->isFloatingType() && + !ValType->isVectorType() && !ValType->isRVVSizelessBuiltinType()) { + Diag(DRE->getBeginLoc(), + diag::err_nontemporal_builtin_must_be_pointer_intfltptr_or_vector) + << PointerArg->getType() << PointerArg->getSourceRange(); + return true; + } + + if (!IsStore) { + TheCall->setType(ValType); + return false; + } + + ExprResult ValArg = TheCall->getArg(1); + InitializedEntity Entity = InitializedEntity::InitializeParameter( + Context, ValType, /*consume*/ false); + ValArg = + SemaRef.PerformCopyInitialization(Entity, SourceLocation(), ValArg); + if (ValArg.isInvalid()) + return true; + + TheCall->setArg(1, ValArg.get()); + TheCall->setType(Context.VoidTy); + return false; + } + + return false; +} + +void SemaRISCV::checkRVVTypeSupport(QualType Ty, SourceLocation Loc, Decl *D, + const llvm::StringMap &FeatureMap) { + ASTContext::BuiltinVectorTypeInfo Info = + SemaRef.Context.getBuiltinVectorTypeInfo(Ty->castAs()); + unsigned EltSize = SemaRef.Context.getTypeSize(Info.ElementType); + unsigned MinElts = Info.EC.getKnownMinValue(); + + if (Info.ElementType->isSpecificBuiltinType(BuiltinType::Double) && + !FeatureMap.lookup("zve64d")) + Diag(Loc, diag::err_riscv_type_requires_extension, D) << Ty << "zve64d"; + // (ELEN, LMUL) pairs of (8, mf8), (16, mf4), (32, mf2), (64, m1) requires at + // least zve64x + else if (((EltSize == 64 && Info.ElementType->isIntegerType()) || + MinElts == 1) && + !FeatureMap.lookup("zve64x")) + Diag(Loc, diag::err_riscv_type_requires_extension, D) << Ty << "zve64x"; + else if (Info.ElementType->isFloat16Type() && !FeatureMap.lookup("zvfh") && + !FeatureMap.lookup("zvfhmin")) + Diag(Loc, diag::err_riscv_type_requires_extension, D) + << Ty << "zvfh or zvfhmin"; + else if (Info.ElementType->isBFloat16Type() && + !FeatureMap.lookup("experimental-zvfbfmin")) + Diag(Loc, diag::err_riscv_type_requires_extension, D) << Ty << "zvfbfmin"; + else if (Info.ElementType->isSpecificBuiltinType(BuiltinType::Float) && + !FeatureMap.lookup("zve32f")) + Diag(Loc, diag::err_riscv_type_requires_extension, D) << Ty << "zve32f"; + // Given that caller already checked isRVVType() before calling this function, + // if we don't have at least zve32x supported, then we need to emit error. + else if (!FeatureMap.lookup("zve32x")) + Diag(Loc, diag::err_riscv_type_requires_extension, D) << Ty << "zve32x"; +} + +/// Are the two types RVV-bitcast-compatible types? I.e. is bitcasting from the +/// first RVV type (e.g. an RVV scalable type) to the second type (e.g. an RVV +/// VLS type) allowed? +/// +/// This will also return false if the two given types do not make sense from +/// the perspective of RVV bitcasts. +bool SemaRISCV::isValidRVVBitcast(QualType srcTy, QualType destTy) { + assert(srcTy->isVectorType() || destTy->isVectorType()); + + auto ValidScalableConversion = [](QualType FirstType, QualType SecondType) { + if (!FirstType->isRVVSizelessBuiltinType()) + return false; + + const auto *VecTy = SecondType->getAs(); + return VecTy && VecTy->getVectorKind() == VectorKind::RVVFixedLengthData; + }; + + return ValidScalableConversion(srcTy, destTy) || + ValidScalableConversion(destTy, srcTy); +} + +SemaRISCV::SemaRISCV(Sema &S) : SemaBase(S) {} + } // namespace clang -- GitLab From a56e6dfd2e6b141b5475c05ad62c378906f565ba Mon Sep 17 00:00:00 2001 From: Florian Hahn Date: Wed, 22 May 2024 09:57:34 +0100 Subject: [PATCH 085/452] [LV] Add test for header mask and invariant compare cost-modeling. Additional test coverage for the VPlan-based cost model work. --- .../AArch64/conditional-branches-cost.ll | 271 ++++++++++++++++++ 1 file changed, 271 insertions(+) diff --git a/llvm/test/Transforms/LoopVectorize/AArch64/conditional-branches-cost.ll b/llvm/test/Transforms/LoopVectorize/AArch64/conditional-branches-cost.ll index 9d8d7036d4f4..a74b0b441771 100644 --- a/llvm/test/Transforms/LoopVectorize/AArch64/conditional-branches-cost.ll +++ b/llvm/test/Transforms/LoopVectorize/AArch64/conditional-branches-cost.ll @@ -634,6 +634,247 @@ exit: ret void } +define i32 @header_mask_and_invariant_compare(ptr %A, ptr %B, ptr %C, ptr %D, ptr %E, i64 %N) "target-features"="+sve" { +; DEFAULT-LABEL: define i32 @header_mask_and_invariant_compare( +; DEFAULT-SAME: ptr [[A:%.*]], ptr [[B:%.*]], ptr [[C:%.*]], ptr [[D:%.*]], ptr [[E:%.*]], i64 [[N:%.*]]) #[[ATTR1:[0-9]+]] { +; DEFAULT-NEXT: entry: +; DEFAULT-NEXT: [[TMP0:%.*]] = add i64 [[N]], 1 +; DEFAULT-NEXT: [[TMP1:%.*]] = call i64 @llvm.vscale.i64() +; DEFAULT-NEXT: [[TMP2:%.*]] = mul i64 [[TMP1]], 4 +; DEFAULT-NEXT: [[TMP3:%.*]] = call i64 @llvm.umax.i64(i64 64, i64 [[TMP2]]) +; DEFAULT-NEXT: [[MIN_ITERS_CHECK:%.*]] = icmp ult i64 [[TMP0]], [[TMP3]] +; DEFAULT-NEXT: br i1 [[MIN_ITERS_CHECK]], label [[SCALAR_PH:%.*]], label [[VECTOR_MEMCHECK:%.*]] +; DEFAULT: vector.memcheck: +; DEFAULT-NEXT: [[SCEVGEP:%.*]] = getelementptr i8, ptr [[E]], i64 4 +; DEFAULT-NEXT: [[TMP4:%.*]] = shl i64 [[N]], 2 +; DEFAULT-NEXT: [[TMP5:%.*]] = add i64 [[TMP4]], 4 +; DEFAULT-NEXT: [[SCEVGEP1:%.*]] = getelementptr i8, ptr [[D]], i64 [[TMP5]] +; DEFAULT-NEXT: [[SCEVGEP2:%.*]] = getelementptr i8, ptr [[A]], i64 4 +; DEFAULT-NEXT: [[SCEVGEP3:%.*]] = getelementptr i8, ptr [[B]], i64 4 +; DEFAULT-NEXT: [[SCEVGEP4:%.*]] = getelementptr i8, ptr [[C]], i64 4 +; DEFAULT-NEXT: [[BOUND0:%.*]] = icmp ult ptr [[E]], [[SCEVGEP1]] +; DEFAULT-NEXT: [[BOUND1:%.*]] = icmp ult ptr [[D]], [[SCEVGEP]] +; DEFAULT-NEXT: [[FOUND_CONFLICT:%.*]] = and i1 [[BOUND0]], [[BOUND1]] +; DEFAULT-NEXT: [[BOUND05:%.*]] = icmp ult ptr [[E]], [[SCEVGEP2]] +; DEFAULT-NEXT: [[BOUND16:%.*]] = icmp ult ptr [[A]], [[SCEVGEP]] +; DEFAULT-NEXT: [[FOUND_CONFLICT7:%.*]] = and i1 [[BOUND05]], [[BOUND16]] +; DEFAULT-NEXT: [[CONFLICT_RDX:%.*]] = or i1 [[FOUND_CONFLICT]], [[FOUND_CONFLICT7]] +; DEFAULT-NEXT: [[BOUND08:%.*]] = icmp ult ptr [[E]], [[SCEVGEP3]] +; DEFAULT-NEXT: [[BOUND19:%.*]] = icmp ult ptr [[B]], [[SCEVGEP]] +; DEFAULT-NEXT: [[FOUND_CONFLICT10:%.*]] = and i1 [[BOUND08]], [[BOUND19]] +; DEFAULT-NEXT: [[CONFLICT_RDX11:%.*]] = or i1 [[CONFLICT_RDX]], [[FOUND_CONFLICT10]] +; DEFAULT-NEXT: [[BOUND012:%.*]] = icmp ult ptr [[E]], [[SCEVGEP4]] +; DEFAULT-NEXT: [[BOUND113:%.*]] = icmp ult ptr [[C]], [[SCEVGEP]] +; DEFAULT-NEXT: [[FOUND_CONFLICT14:%.*]] = and i1 [[BOUND012]], [[BOUND113]] +; DEFAULT-NEXT: [[CONFLICT_RDX15:%.*]] = or i1 [[CONFLICT_RDX11]], [[FOUND_CONFLICT14]] +; DEFAULT-NEXT: [[BOUND016:%.*]] = icmp ult ptr [[D]], [[SCEVGEP2]] +; DEFAULT-NEXT: [[BOUND117:%.*]] = icmp ult ptr [[A]], [[SCEVGEP1]] +; DEFAULT-NEXT: [[FOUND_CONFLICT18:%.*]] = and i1 [[BOUND016]], [[BOUND117]] +; DEFAULT-NEXT: [[CONFLICT_RDX19:%.*]] = or i1 [[CONFLICT_RDX15]], [[FOUND_CONFLICT18]] +; DEFAULT-NEXT: [[BOUND020:%.*]] = icmp ult ptr [[D]], [[SCEVGEP3]] +; DEFAULT-NEXT: [[BOUND121:%.*]] = icmp ult ptr [[B]], [[SCEVGEP1]] +; DEFAULT-NEXT: [[FOUND_CONFLICT22:%.*]] = and i1 [[BOUND020]], [[BOUND121]] +; DEFAULT-NEXT: [[CONFLICT_RDX23:%.*]] = or i1 [[CONFLICT_RDX19]], [[FOUND_CONFLICT22]] +; DEFAULT-NEXT: [[BOUND024:%.*]] = icmp ult ptr [[D]], [[SCEVGEP4]] +; DEFAULT-NEXT: [[BOUND125:%.*]] = icmp ult ptr [[C]], [[SCEVGEP1]] +; DEFAULT-NEXT: [[FOUND_CONFLICT26:%.*]] = and i1 [[BOUND024]], [[BOUND125]] +; DEFAULT-NEXT: [[CONFLICT_RDX27:%.*]] = or i1 [[CONFLICT_RDX23]], [[FOUND_CONFLICT26]] +; DEFAULT-NEXT: br i1 [[CONFLICT_RDX27]], label [[SCALAR_PH]], label [[VECTOR_PH:%.*]] +; DEFAULT: vector.ph: +; DEFAULT-NEXT: [[TMP6:%.*]] = call i64 @llvm.vscale.i64() +; DEFAULT-NEXT: [[TMP7:%.*]] = mul i64 [[TMP6]], 4 +; DEFAULT-NEXT: [[N_MOD_VF:%.*]] = urem i64 [[TMP0]], [[TMP7]] +; DEFAULT-NEXT: [[N_VEC:%.*]] = sub i64 [[TMP0]], [[N_MOD_VF]] +; DEFAULT-NEXT: [[TMP8:%.*]] = call i64 @llvm.vscale.i64() +; DEFAULT-NEXT: [[TMP9:%.*]] = mul i64 [[TMP8]], 4 +; DEFAULT-NEXT: [[BROADCAST_SPLATINSERT32:%.*]] = insertelement poison, ptr [[E]], i64 0 +; DEFAULT-NEXT: [[BROADCAST_SPLAT33:%.*]] = shufflevector [[BROADCAST_SPLATINSERT32]], poison, zeroinitializer +; DEFAULT-NEXT: br label [[VECTOR_BODY:%.*]] +; DEFAULT: vector.body: +; DEFAULT-NEXT: [[INDEX:%.*]] = phi i64 [ 0, [[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], [[VECTOR_BODY]] ] +; DEFAULT-NEXT: [[TMP10:%.*]] = add i64 [[INDEX]], 0 +; DEFAULT-NEXT: [[TMP11:%.*]] = load i32, ptr [[A]], align 4, !alias.scope [[META9:![0-9]+]] +; DEFAULT-NEXT: [[BROADCAST_SPLATINSERT28:%.*]] = insertelement poison, i32 [[TMP11]], i64 0 +; DEFAULT-NEXT: [[BROADCAST_SPLAT29:%.*]] = shufflevector [[BROADCAST_SPLATINSERT28]], poison, zeroinitializer +; DEFAULT-NEXT: [[TMP12:%.*]] = load i32, ptr [[B]], align 4, !alias.scope [[META12:![0-9]+]] +; DEFAULT-NEXT: [[BROADCAST_SPLATINSERT:%.*]] = insertelement poison, i32 [[TMP12]], i64 0 +; DEFAULT-NEXT: [[BROADCAST_SPLAT:%.*]] = shufflevector [[BROADCAST_SPLATINSERT]], poison, zeroinitializer +; DEFAULT-NEXT: [[TMP13:%.*]] = or [[BROADCAST_SPLAT]], [[BROADCAST_SPLAT29]] +; DEFAULT-NEXT: [[TMP14:%.*]] = load i32, ptr [[C]], align 4, !alias.scope [[META14:![0-9]+]] +; DEFAULT-NEXT: [[BROADCAST_SPLATINSERT30:%.*]] = insertelement poison, i32 [[TMP14]], i64 0 +; DEFAULT-NEXT: [[BROADCAST_SPLAT31:%.*]] = shufflevector [[BROADCAST_SPLATINSERT30]], poison, zeroinitializer +; DEFAULT-NEXT: [[TMP15:%.*]] = icmp ugt [[BROADCAST_SPLAT31]], [[TMP13]] +; DEFAULT-NEXT: [[TMP16:%.*]] = getelementptr i32, ptr [[D]], i64 [[TMP10]] +; DEFAULT-NEXT: call void @llvm.masked.scatter.nxv4i32.nxv4p0( [[TMP13]], [[BROADCAST_SPLAT33]], i32 4, [[TMP15]]), !alias.scope [[META16:![0-9]+]], !noalias [[META18:![0-9]+]] +; DEFAULT-NEXT: [[TMP17:%.*]] = getelementptr i32, ptr [[TMP16]], i32 0 +; DEFAULT-NEXT: call void @llvm.masked.store.nxv4i32.p0( zeroinitializer, ptr [[TMP17]], i32 4, [[TMP15]]), !alias.scope [[META20:![0-9]+]], !noalias [[META21:![0-9]+]] +; DEFAULT-NEXT: [[INDEX_NEXT]] = add nuw i64 [[INDEX]], [[TMP9]] +; DEFAULT-NEXT: [[TMP18:%.*]] = icmp eq i64 [[INDEX_NEXT]], [[N_VEC]] +; DEFAULT-NEXT: br i1 [[TMP18]], label [[MIDDLE_BLOCK:%.*]], label [[VECTOR_BODY]], !llvm.loop [[LOOP22:![0-9]+]] +; DEFAULT: middle.block: +; DEFAULT-NEXT: [[CMP_N:%.*]] = icmp eq i64 [[TMP0]], [[N_VEC]] +; DEFAULT-NEXT: br i1 [[CMP_N]], label [[EXIT:%.*]], label [[SCALAR_PH]] +; DEFAULT: scalar.ph: +; DEFAULT-NEXT: [[BC_RESUME_VAL:%.*]] = phi i64 [ [[N_VEC]], [[MIDDLE_BLOCK]] ], [ 0, [[ENTRY:%.*]] ], [ 0, [[VECTOR_MEMCHECK]] ] +; DEFAULT-NEXT: br label [[LOOP_HEADER:%.*]] +; DEFAULT: loop.header: +; DEFAULT-NEXT: [[IV:%.*]] = phi i64 [ [[BC_RESUME_VAL]], [[SCALAR_PH]] ], [ [[IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ] +; DEFAULT-NEXT: [[L_A:%.*]] = load i32, ptr [[A]], align 4 +; DEFAULT-NEXT: [[L_B:%.*]] = load i32, ptr [[B]], align 4 +; DEFAULT-NEXT: [[OR:%.*]] = or i32 [[L_B]], [[L_A]] +; DEFAULT-NEXT: [[L_C:%.*]] = load i32, ptr [[C]], align 4 +; DEFAULT-NEXT: [[C_0:%.*]] = icmp ugt i32 [[L_C]], [[OR]] +; DEFAULT-NEXT: br i1 [[C_0]], label [[IF_THEN:%.*]], label [[LOOP_LATCH]] +; DEFAULT: if.then: +; DEFAULT-NEXT: [[GEP_D:%.*]] = getelementptr i32, ptr [[D]], i64 [[IV]] +; DEFAULT-NEXT: store i32 [[OR]], ptr [[E]], align 4 +; DEFAULT-NEXT: store i32 0, ptr [[GEP_D]], align 4 +; DEFAULT-NEXT: br label [[LOOP_LATCH]] +; DEFAULT: loop.latch: +; DEFAULT-NEXT: [[IV_NEXT]] = add i64 [[IV]], 1 +; DEFAULT-NEXT: [[C_1:%.*]] = icmp eq i64 [[IV]], [[N]] +; DEFAULT-NEXT: br i1 [[C_1]], label [[EXIT]], label [[LOOP_HEADER]], !llvm.loop [[LOOP23:![0-9]+]] +; DEFAULT: exit: +; DEFAULT-NEXT: ret i32 0 +; +; PRED-LABEL: define i32 @header_mask_and_invariant_compare( +; PRED-SAME: ptr [[A:%.*]], ptr [[B:%.*]], ptr [[C:%.*]], ptr [[D:%.*]], ptr [[E:%.*]], i64 [[N:%.*]]) #[[ATTR1:[0-9]+]] { +; PRED-NEXT: entry: +; PRED-NEXT: [[TMP0:%.*]] = add i64 [[N]], 1 +; PRED-NEXT: br i1 false, label [[SCALAR_PH:%.*]], label [[VECTOR_MEMCHECK:%.*]] +; PRED: vector.memcheck: +; PRED-NEXT: [[SCEVGEP:%.*]] = getelementptr i8, ptr [[E]], i64 4 +; PRED-NEXT: [[TMP1:%.*]] = shl i64 [[N]], 2 +; PRED-NEXT: [[TMP2:%.*]] = add i64 [[TMP1]], 4 +; PRED-NEXT: [[SCEVGEP1:%.*]] = getelementptr i8, ptr [[D]], i64 [[TMP2]] +; PRED-NEXT: [[SCEVGEP2:%.*]] = getelementptr i8, ptr [[A]], i64 4 +; PRED-NEXT: [[SCEVGEP3:%.*]] = getelementptr i8, ptr [[B]], i64 4 +; PRED-NEXT: [[SCEVGEP4:%.*]] = getelementptr i8, ptr [[C]], i64 4 +; PRED-NEXT: [[BOUND0:%.*]] = icmp ult ptr [[E]], [[SCEVGEP1]] +; PRED-NEXT: [[BOUND1:%.*]] = icmp ult ptr [[D]], [[SCEVGEP]] +; PRED-NEXT: [[FOUND_CONFLICT:%.*]] = and i1 [[BOUND0]], [[BOUND1]] +; PRED-NEXT: [[BOUND05:%.*]] = icmp ult ptr [[E]], [[SCEVGEP2]] +; PRED-NEXT: [[BOUND16:%.*]] = icmp ult ptr [[A]], [[SCEVGEP]] +; PRED-NEXT: [[FOUND_CONFLICT7:%.*]] = and i1 [[BOUND05]], [[BOUND16]] +; PRED-NEXT: [[CONFLICT_RDX:%.*]] = or i1 [[FOUND_CONFLICT]], [[FOUND_CONFLICT7]] +; PRED-NEXT: [[BOUND08:%.*]] = icmp ult ptr [[E]], [[SCEVGEP3]] +; PRED-NEXT: [[BOUND19:%.*]] = icmp ult ptr [[B]], [[SCEVGEP]] +; PRED-NEXT: [[FOUND_CONFLICT10:%.*]] = and i1 [[BOUND08]], [[BOUND19]] +; PRED-NEXT: [[CONFLICT_RDX11:%.*]] = or i1 [[CONFLICT_RDX]], [[FOUND_CONFLICT10]] +; PRED-NEXT: [[BOUND012:%.*]] = icmp ult ptr [[E]], [[SCEVGEP4]] +; PRED-NEXT: [[BOUND113:%.*]] = icmp ult ptr [[C]], [[SCEVGEP]] +; PRED-NEXT: [[FOUND_CONFLICT14:%.*]] = and i1 [[BOUND012]], [[BOUND113]] +; PRED-NEXT: [[CONFLICT_RDX15:%.*]] = or i1 [[CONFLICT_RDX11]], [[FOUND_CONFLICT14]] +; PRED-NEXT: [[BOUND016:%.*]] = icmp ult ptr [[D]], [[SCEVGEP2]] +; PRED-NEXT: [[BOUND117:%.*]] = icmp ult ptr [[A]], [[SCEVGEP1]] +; PRED-NEXT: [[FOUND_CONFLICT18:%.*]] = and i1 [[BOUND016]], [[BOUND117]] +; PRED-NEXT: [[CONFLICT_RDX19:%.*]] = or i1 [[CONFLICT_RDX15]], [[FOUND_CONFLICT18]] +; PRED-NEXT: [[BOUND020:%.*]] = icmp ult ptr [[D]], [[SCEVGEP3]] +; PRED-NEXT: [[BOUND121:%.*]] = icmp ult ptr [[B]], [[SCEVGEP1]] +; PRED-NEXT: [[FOUND_CONFLICT22:%.*]] = and i1 [[BOUND020]], [[BOUND121]] +; PRED-NEXT: [[CONFLICT_RDX23:%.*]] = or i1 [[CONFLICT_RDX19]], [[FOUND_CONFLICT22]] +; PRED-NEXT: [[BOUND024:%.*]] = icmp ult ptr [[D]], [[SCEVGEP4]] +; PRED-NEXT: [[BOUND125:%.*]] = icmp ult ptr [[C]], [[SCEVGEP1]] +; PRED-NEXT: [[FOUND_CONFLICT26:%.*]] = and i1 [[BOUND024]], [[BOUND125]] +; PRED-NEXT: [[CONFLICT_RDX27:%.*]] = or i1 [[CONFLICT_RDX23]], [[FOUND_CONFLICT26]] +; PRED-NEXT: br i1 [[CONFLICT_RDX27]], label [[SCALAR_PH]], label [[VECTOR_PH:%.*]] +; PRED: vector.ph: +; PRED-NEXT: [[TMP3:%.*]] = call i64 @llvm.vscale.i64() +; PRED-NEXT: [[TMP4:%.*]] = mul i64 [[TMP3]], 4 +; PRED-NEXT: [[TMP5:%.*]] = call i64 @llvm.vscale.i64() +; PRED-NEXT: [[TMP6:%.*]] = mul i64 [[TMP5]], 4 +; PRED-NEXT: [[TMP7:%.*]] = sub i64 [[TMP6]], 1 +; PRED-NEXT: [[N_RND_UP:%.*]] = add i64 [[TMP0]], [[TMP7]] +; PRED-NEXT: [[N_MOD_VF:%.*]] = urem i64 [[N_RND_UP]], [[TMP4]] +; PRED-NEXT: [[N_VEC:%.*]] = sub i64 [[N_RND_UP]], [[N_MOD_VF]] +; PRED-NEXT: [[TMP8:%.*]] = call i64 @llvm.vscale.i64() +; PRED-NEXT: [[TMP9:%.*]] = mul i64 [[TMP8]], 4 +; PRED-NEXT: [[TMP10:%.*]] = call i64 @llvm.vscale.i64() +; PRED-NEXT: [[TMP11:%.*]] = mul i64 [[TMP10]], 4 +; PRED-NEXT: [[TMP12:%.*]] = sub i64 [[TMP0]], [[TMP11]] +; PRED-NEXT: [[TMP13:%.*]] = icmp ugt i64 [[TMP0]], [[TMP11]] +; PRED-NEXT: [[TMP14:%.*]] = select i1 [[TMP13]], i64 [[TMP12]], i64 0 +; PRED-NEXT: [[ACTIVE_LANE_MASK_ENTRY:%.*]] = call @llvm.get.active.lane.mask.nxv4i1.i64(i64 0, i64 [[TMP0]]) +; PRED-NEXT: [[BROADCAST_SPLATINSERT32:%.*]] = insertelement poison, ptr [[E]], i64 0 +; PRED-NEXT: [[BROADCAST_SPLAT33:%.*]] = shufflevector [[BROADCAST_SPLATINSERT32]], poison, zeroinitializer +; PRED-NEXT: br label [[VECTOR_BODY:%.*]] +; PRED: vector.body: +; PRED-NEXT: [[INDEX:%.*]] = phi i64 [ 0, [[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], [[VECTOR_BODY]] ] +; PRED-NEXT: [[ACTIVE_LANE_MASK:%.*]] = phi [ [[ACTIVE_LANE_MASK_ENTRY]], [[VECTOR_PH]] ], [ [[ACTIVE_LANE_MASK_NEXT:%.*]], [[VECTOR_BODY]] ] +; PRED-NEXT: [[TMP15:%.*]] = add i64 [[INDEX]], 0 +; PRED-NEXT: [[TMP16:%.*]] = load i32, ptr [[A]], align 4, !alias.scope [[META6:![0-9]+]] +; PRED-NEXT: [[BROADCAST_SPLATINSERT28:%.*]] = insertelement poison, i32 [[TMP16]], i64 0 +; PRED-NEXT: [[BROADCAST_SPLAT29:%.*]] = shufflevector [[BROADCAST_SPLATINSERT28]], poison, zeroinitializer +; PRED-NEXT: [[TMP17:%.*]] = load i32, ptr [[B]], align 4, !alias.scope [[META9:![0-9]+]] +; PRED-NEXT: [[BROADCAST_SPLATINSERT:%.*]] = insertelement poison, i32 [[TMP17]], i64 0 +; PRED-NEXT: [[BROADCAST_SPLAT:%.*]] = shufflevector [[BROADCAST_SPLATINSERT]], poison, zeroinitializer +; PRED-NEXT: [[TMP18:%.*]] = or [[BROADCAST_SPLAT]], [[BROADCAST_SPLAT29]] +; PRED-NEXT: [[TMP19:%.*]] = load i32, ptr [[C]], align 4, !alias.scope [[META11:![0-9]+]] +; PRED-NEXT: [[BROADCAST_SPLATINSERT30:%.*]] = insertelement poison, i32 [[TMP19]], i64 0 +; PRED-NEXT: [[BROADCAST_SPLAT31:%.*]] = shufflevector [[BROADCAST_SPLATINSERT30]], poison, zeroinitializer +; PRED-NEXT: [[TMP20:%.*]] = icmp ugt [[BROADCAST_SPLAT31]], [[TMP18]] +; PRED-NEXT: [[TMP21:%.*]] = select [[ACTIVE_LANE_MASK]], [[TMP20]], zeroinitializer +; PRED-NEXT: [[TMP22:%.*]] = getelementptr i32, ptr [[D]], i64 [[TMP15]] +; PRED-NEXT: call void @llvm.masked.scatter.nxv4i32.nxv4p0( [[TMP18]], [[BROADCAST_SPLAT33]], i32 4, [[TMP21]]), !alias.scope [[META13:![0-9]+]], !noalias [[META15:![0-9]+]] +; PRED-NEXT: [[TMP23:%.*]] = getelementptr i32, ptr [[TMP22]], i32 0 +; PRED-NEXT: call void @llvm.masked.store.nxv4i32.p0( zeroinitializer, ptr [[TMP23]], i32 4, [[TMP21]]), !alias.scope [[META17:![0-9]+]], !noalias [[META18:![0-9]+]] +; PRED-NEXT: [[INDEX_NEXT]] = add i64 [[INDEX]], [[TMP9]] +; PRED-NEXT: [[ACTIVE_LANE_MASK_NEXT]] = call @llvm.get.active.lane.mask.nxv4i1.i64(i64 [[INDEX]], i64 [[TMP14]]) +; PRED-NEXT: [[TMP24:%.*]] = xor [[ACTIVE_LANE_MASK_NEXT]], shufflevector ( insertelement ( poison, i1 true, i64 0), poison, zeroinitializer) +; PRED-NEXT: [[TMP25:%.*]] = extractelement [[TMP24]], i32 0 +; PRED-NEXT: br i1 [[TMP25]], label [[MIDDLE_BLOCK:%.*]], label [[VECTOR_BODY]], !llvm.loop [[LOOP19:![0-9]+]] +; PRED: middle.block: +; PRED-NEXT: br i1 true, label [[EXIT:%.*]], label [[SCALAR_PH]] +; PRED: scalar.ph: +; PRED-NEXT: [[BC_RESUME_VAL:%.*]] = phi i64 [ [[N_VEC]], [[MIDDLE_BLOCK]] ], [ 0, [[ENTRY:%.*]] ], [ 0, [[VECTOR_MEMCHECK]] ] +; PRED-NEXT: br label [[LOOP_HEADER:%.*]] +; PRED: loop.header: +; PRED-NEXT: [[IV:%.*]] = phi i64 [ [[BC_RESUME_VAL]], [[SCALAR_PH]] ], [ [[IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ] +; PRED-NEXT: [[L_A:%.*]] = load i32, ptr [[A]], align 4 +; PRED-NEXT: [[L_B:%.*]] = load i32, ptr [[B]], align 4 +; PRED-NEXT: [[OR:%.*]] = or i32 [[L_B]], [[L_A]] +; PRED-NEXT: [[L_C:%.*]] = load i32, ptr [[C]], align 4 +; PRED-NEXT: [[C_0:%.*]] = icmp ugt i32 [[L_C]], [[OR]] +; PRED-NEXT: br i1 [[C_0]], label [[IF_THEN:%.*]], label [[LOOP_LATCH]] +; PRED: if.then: +; PRED-NEXT: [[GEP_D:%.*]] = getelementptr i32, ptr [[D]], i64 [[IV]] +; PRED-NEXT: store i32 [[OR]], ptr [[E]], align 4 +; PRED-NEXT: store i32 0, ptr [[GEP_D]], align 4 +; PRED-NEXT: br label [[LOOP_LATCH]] +; PRED: loop.latch: +; PRED-NEXT: [[IV_NEXT]] = add i64 [[IV]], 1 +; PRED-NEXT: [[C_1:%.*]] = icmp eq i64 [[IV]], [[N]] +; PRED-NEXT: br i1 [[C_1]], label [[EXIT]], label [[LOOP_HEADER]], !llvm.loop [[LOOP20:![0-9]+]] +; PRED: exit: +; PRED-NEXT: ret i32 0 +; +entry: + br label %loop.header + +loop.header: + %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop.latch ] + %l.A = load i32, ptr %A, align 4 + %l.B = load i32, ptr %B, align 4 + %or = or i32 %l.B, %l.A + %l.C = load i32, ptr %C, align 4 + %c.0 = icmp ugt i32 %l.C, %or + br i1 %c.0, label %if.then, label %loop.latch + +if.then: + %gep.D = getelementptr i32, ptr %D, i64 %iv + store i32 %or, ptr %E, align 4 + store i32 0, ptr %gep.D, align 4 + br label %loop.latch + +loop.latch: + %iv.next = add i64 %iv, 1 + %c.1 = icmp eq i64 %iv, %N + br i1 %c.1, label %exit, label %loop.header + +exit: + ret i32 0 +} + ;. ; DEFAULT: [[LOOP0]] = distinct !{[[LOOP0]], [[META1:![0-9]+]], [[META2:![0-9]+]]} ; DEFAULT: [[META1]] = !{!"llvm.loop.isvectorized", i32 1} @@ -644,6 +885,21 @@ exit: ; DEFAULT: [[LOOP6]] = distinct !{[[LOOP6]], [[META1]], [[META2]]} ; DEFAULT: [[LOOP7]] = distinct !{[[LOOP7]], [[META1]], [[META2]]} ; DEFAULT: [[LOOP8]] = distinct !{[[LOOP8]], [[META2]], [[META1]]} +; DEFAULT: [[META9]] = !{[[META10:![0-9]+]]} +; DEFAULT: [[META10]] = distinct !{[[META10]], [[META11:![0-9]+]]} +; DEFAULT: [[META11]] = distinct !{[[META11]], !"LVerDomain"} +; DEFAULT: [[META12]] = !{[[META13:![0-9]+]]} +; DEFAULT: [[META13]] = distinct !{[[META13]], [[META11]]} +; DEFAULT: [[META14]] = !{[[META15:![0-9]+]]} +; DEFAULT: [[META15]] = distinct !{[[META15]], [[META11]]} +; DEFAULT: [[META16]] = !{[[META17:![0-9]+]]} +; DEFAULT: [[META17]] = distinct !{[[META17]], [[META11]]} +; DEFAULT: [[META18]] = !{[[META19:![0-9]+]], [[META10]], [[META13]], [[META15]]} +; DEFAULT: [[META19]] = distinct !{[[META19]], [[META11]]} +; DEFAULT: [[META20]] = !{[[META19]]} +; DEFAULT: [[META21]] = !{[[META10]], [[META13]], [[META15]]} +; DEFAULT: [[LOOP22]] = distinct !{[[LOOP22]], [[META1]], [[META2]]} +; DEFAULT: [[LOOP23]] = distinct !{[[LOOP23]], [[META1]]} ;. ; PRED: [[LOOP0]] = distinct !{[[LOOP0]], [[META1:![0-9]+]], [[META2:![0-9]+]]} ; PRED: [[META1]] = !{!"llvm.loop.isvectorized", i32 1} @@ -651,4 +907,19 @@ exit: ; PRED: [[LOOP3]] = distinct !{[[LOOP3]], [[META2]], [[META1]]} ; PRED: [[LOOP4]] = distinct !{[[LOOP4]], [[META1]], [[META2]]} ; PRED: [[LOOP5]] = distinct !{[[LOOP5]], [[META2]], [[META1]]} +; PRED: [[META6]] = !{[[META7:![0-9]+]]} +; PRED: [[META7]] = distinct !{[[META7]], [[META8:![0-9]+]]} +; PRED: [[META8]] = distinct !{[[META8]], !"LVerDomain"} +; PRED: [[META9]] = !{[[META10:![0-9]+]]} +; PRED: [[META10]] = distinct !{[[META10]], [[META8]]} +; PRED: [[META11]] = !{[[META12:![0-9]+]]} +; PRED: [[META12]] = distinct !{[[META12]], [[META8]]} +; PRED: [[META13]] = !{[[META14:![0-9]+]]} +; PRED: [[META14]] = distinct !{[[META14]], [[META8]]} +; PRED: [[META15]] = !{[[META16:![0-9]+]], [[META7]], [[META10]], [[META12]]} +; PRED: [[META16]] = distinct !{[[META16]], [[META8]]} +; PRED: [[META17]] = !{[[META16]]} +; PRED: [[META18]] = !{[[META7]], [[META10]], [[META12]]} +; PRED: [[LOOP19]] = distinct !{[[LOOP19]], [[META1]], [[META2]]} +; PRED: [[LOOP20]] = distinct !{[[LOOP20]], [[META1]]} ;. -- GitLab From f98a3dd7a23ca1a85f62b38a2a7e82a53f80070b Mon Sep 17 00:00:00 2001 From: Mark de Wever Date: Wed, 22 May 2024 11:05:01 +0200 Subject: [PATCH 086/452] [NFC][libc++][test] Removes C++98 support. (#92930) Libc++ has no separate C++98 support, it uses C++03 instead. This removes some obsolete c++98 markers in the test. Thanks to @StephanTLavavej for spotting this. --- .../containers/associative/map/map.value_compare/types.pass.cpp | 2 +- .../associative/multimap/multimap.value_compare/types.pass.cpp | 2 +- .../predef.iterators/counted.iterator/implicit_ctad.pass.cpp | 2 +- .../back.insert.iterator/implicit_ctad.pass.cpp | 2 +- .../front.insert.iterator/implicit_ctad.pass.cpp | 2 +- .../move.iterators/move.iterator/implicit_ctad.pass.cpp | 2 +- .../strings/string.view/string.view.deduct/implicit.pass.cpp | 2 +- .../thread.lock/thread.lock.guard/implicit_ctad.pass.cpp | 2 +- .../thread.lock/thread.lock.scoped/implicit_ctad.pass.cpp | 2 +- .../thread.lock/thread.lock.shared/implicit_ctad.pass.cpp | 2 +- .../thread.lock/thread.lock.unique/implicit_ctad.pass.cpp | 2 +- .../func.search/func.search.bm/implicit_ctad.pass.cpp | 2 +- .../func.search/func.search.bmh/implicit_ctad.pass.cpp | 2 +- .../func.search/func.search.default/implicit_ctad.pass.cpp | 2 +- .../function.objects/operations.implicit_ctad.pass.cpp | 2 +- 15 files changed, 15 insertions(+), 15 deletions(-) diff --git a/libcxx/test/std/containers/associative/map/map.value_compare/types.pass.cpp b/libcxx/test/std/containers/associative/map/map.value_compare/types.pass.cpp index 1d6069933eea..52111ddb3f27 100644 --- a/libcxx/test/std/containers/associative/map/map.value_compare/types.pass.cpp +++ b/libcxx/test/std/containers/associative/map/map.value_compare/types.pass.cpp @@ -10,7 +10,7 @@ // class value_compare -// REQUIRES: c++98 || c++03 || c++11 || c++14 +// REQUIRES: c++03 || c++11 || c++14 #include #include diff --git a/libcxx/test/std/containers/associative/multimap/multimap.value_compare/types.pass.cpp b/libcxx/test/std/containers/associative/multimap/multimap.value_compare/types.pass.cpp index 6ecaf9247ebe..0d0c74f29f42 100644 --- a/libcxx/test/std/containers/associative/multimap/multimap.value_compare/types.pass.cpp +++ b/libcxx/test/std/containers/associative/multimap/multimap.value_compare/types.pass.cpp @@ -10,7 +10,7 @@ // class value_compare -// REQUIRES: c++98 || c++03 || c++11 || c++14 +// REQUIRES: c++03 || c++11 || c++14 #include #include diff --git a/libcxx/test/std/iterators/predef.iterators/counted.iterator/implicit_ctad.pass.cpp b/libcxx/test/std/iterators/predef.iterators/counted.iterator/implicit_ctad.pass.cpp index 2786dfbb7a60..5b4853a783c2 100644 --- a/libcxx/test/std/iterators/predef.iterators/counted.iterator/implicit_ctad.pass.cpp +++ b/libcxx/test/std/iterators/predef.iterators/counted.iterator/implicit_ctad.pass.cpp @@ -6,7 +6,7 @@ // //===----------------------------------------------------------------------===// -// UNSUPPORTED: c++98, c++03, c++11, c++14, c++17 +// UNSUPPORTED: c++03, c++11, c++14, c++17 // counted_iterator diff --git a/libcxx/test/std/iterators/predef.iterators/insert.iterators/back.insert.iterator/implicit_ctad.pass.cpp b/libcxx/test/std/iterators/predef.iterators/insert.iterators/back.insert.iterator/implicit_ctad.pass.cpp index 10729e0029d0..3c2e6af98d55 100644 --- a/libcxx/test/std/iterators/predef.iterators/insert.iterators/back.insert.iterator/implicit_ctad.pass.cpp +++ b/libcxx/test/std/iterators/predef.iterators/insert.iterators/back.insert.iterator/implicit_ctad.pass.cpp @@ -6,7 +6,7 @@ // //===----------------------------------------------------------------------===// -// UNSUPPORTED: c++98, c++03, c++11, c++14 +// UNSUPPORTED: c++03, c++11, c++14 // diff --git a/libcxx/test/std/iterators/predef.iterators/insert.iterators/front.insert.iterator/implicit_ctad.pass.cpp b/libcxx/test/std/iterators/predef.iterators/insert.iterators/front.insert.iterator/implicit_ctad.pass.cpp index f91d472e9ea2..f9b086aea4fc 100644 --- a/libcxx/test/std/iterators/predef.iterators/insert.iterators/front.insert.iterator/implicit_ctad.pass.cpp +++ b/libcxx/test/std/iterators/predef.iterators/insert.iterators/front.insert.iterator/implicit_ctad.pass.cpp @@ -6,7 +6,7 @@ // //===----------------------------------------------------------------------===// -// UNSUPPORTED: c++98, c++03, c++11, c++14 +// UNSUPPORTED: c++03, c++11, c++14 // diff --git a/libcxx/test/std/iterators/predef.iterators/move.iterators/move.iterator/implicit_ctad.pass.cpp b/libcxx/test/std/iterators/predef.iterators/move.iterators/move.iterator/implicit_ctad.pass.cpp index e5744465daa9..b84a07017dae 100644 --- a/libcxx/test/std/iterators/predef.iterators/move.iterators/move.iterator/implicit_ctad.pass.cpp +++ b/libcxx/test/std/iterators/predef.iterators/move.iterators/move.iterator/implicit_ctad.pass.cpp @@ -6,7 +6,7 @@ // //===----------------------------------------------------------------------===// -// UNSUPPORTED: c++98, c++03, c++11, c++14 +// UNSUPPORTED: c++03, c++11, c++14 // diff --git a/libcxx/test/std/strings/string.view/string.view.deduct/implicit.pass.cpp b/libcxx/test/std/strings/string.view/string.view.deduct/implicit.pass.cpp index c76c4a01c696..36584f76bebd 100644 --- a/libcxx/test/std/strings/string.view/string.view.deduct/implicit.pass.cpp +++ b/libcxx/test/std/strings/string.view/string.view.deduct/implicit.pass.cpp @@ -6,7 +6,7 @@ // //===----------------------------------------------------------------------===// -// UNSUPPORTED: c++98, c++03, c++11, c++14 +// UNSUPPORTED: c++03, c++11, c++14 // diff --git a/libcxx/test/std/thread/thread.mutex/thread.lock/thread.lock.guard/implicit_ctad.pass.cpp b/libcxx/test/std/thread/thread.mutex/thread.lock/thread.lock.guard/implicit_ctad.pass.cpp index b75441733482..9319ec0dba04 100644 --- a/libcxx/test/std/thread/thread.mutex/thread.lock/thread.lock.guard/implicit_ctad.pass.cpp +++ b/libcxx/test/std/thread/thread.mutex/thread.lock/thread.lock.guard/implicit_ctad.pass.cpp @@ -7,7 +7,7 @@ //===----------------------------------------------------------------------===// // UNSUPPORTED: no-threads -// UNSUPPORTED: c++98, c++03, c++11, c++14 +// UNSUPPORTED: c++03, c++11, c++14 // diff --git a/libcxx/test/std/thread/thread.mutex/thread.lock/thread.lock.scoped/implicit_ctad.pass.cpp b/libcxx/test/std/thread/thread.mutex/thread.lock/thread.lock.scoped/implicit_ctad.pass.cpp index 7305b48c53a9..86bda3a9c6b9 100644 --- a/libcxx/test/std/thread/thread.mutex/thread.lock/thread.lock.scoped/implicit_ctad.pass.cpp +++ b/libcxx/test/std/thread/thread.mutex/thread.lock/thread.lock.scoped/implicit_ctad.pass.cpp @@ -7,7 +7,7 @@ //===----------------------------------------------------------------------===// // UNSUPPORTED: no-threads -// UNSUPPORTED: c++98, c++03, c++11, c++14 +// UNSUPPORTED: c++03, c++11, c++14 // diff --git a/libcxx/test/std/thread/thread.mutex/thread.lock/thread.lock.shared/implicit_ctad.pass.cpp b/libcxx/test/std/thread/thread.mutex/thread.lock/thread.lock.shared/implicit_ctad.pass.cpp index 9a595f90ed4f..826ec2b558f0 100644 --- a/libcxx/test/std/thread/thread.mutex/thread.lock/thread.lock.shared/implicit_ctad.pass.cpp +++ b/libcxx/test/std/thread/thread.mutex/thread.lock/thread.lock.shared/implicit_ctad.pass.cpp @@ -7,7 +7,7 @@ //===----------------------------------------------------------------------===// // UNSUPPORTED: no-threads -// UNSUPPORTED: c++98, c++03, c++11, c++14 +// UNSUPPORTED: c++03, c++11, c++14 // diff --git a/libcxx/test/std/thread/thread.mutex/thread.lock/thread.lock.unique/implicit_ctad.pass.cpp b/libcxx/test/std/thread/thread.mutex/thread.lock/thread.lock.unique/implicit_ctad.pass.cpp index ffe651c6b744..337ad4c45a94 100644 --- a/libcxx/test/std/thread/thread.mutex/thread.lock/thread.lock.unique/implicit_ctad.pass.cpp +++ b/libcxx/test/std/thread/thread.mutex/thread.lock/thread.lock.unique/implicit_ctad.pass.cpp @@ -7,7 +7,7 @@ //===----------------------------------------------------------------------===// // UNSUPPORTED: no-threads -// UNSUPPORTED: c++98, c++03, c++11, c++14 +// UNSUPPORTED: c++03, c++11, c++14 // diff --git a/libcxx/test/std/utilities/function.objects/func.search/func.search.bm/implicit_ctad.pass.cpp b/libcxx/test/std/utilities/function.objects/func.search/func.search.bm/implicit_ctad.pass.cpp index 863b4a5c2569..50c89d6b8db6 100644 --- a/libcxx/test/std/utilities/function.objects/func.search/func.search.bm/implicit_ctad.pass.cpp +++ b/libcxx/test/std/utilities/function.objects/func.search/func.search.bm/implicit_ctad.pass.cpp @@ -6,7 +6,7 @@ // //===----------------------------------------------------------------------===// -// UNSUPPORTED: c++98, c++03, c++11, c++14 +// UNSUPPORTED: c++03, c++11, c++14 // diff --git a/libcxx/test/std/utilities/function.objects/func.search/func.search.bmh/implicit_ctad.pass.cpp b/libcxx/test/std/utilities/function.objects/func.search/func.search.bmh/implicit_ctad.pass.cpp index 778f6d3bd2cb..9cb4ef5afbb5 100644 --- a/libcxx/test/std/utilities/function.objects/func.search/func.search.bmh/implicit_ctad.pass.cpp +++ b/libcxx/test/std/utilities/function.objects/func.search/func.search.bmh/implicit_ctad.pass.cpp @@ -6,7 +6,7 @@ // //===----------------------------------------------------------------------===// -// UNSUPPORTED: c++98, c++03, c++11, c++14 +// UNSUPPORTED: c++03, c++11, c++14 // diff --git a/libcxx/test/std/utilities/function.objects/func.search/func.search.default/implicit_ctad.pass.cpp b/libcxx/test/std/utilities/function.objects/func.search/func.search.default/implicit_ctad.pass.cpp index 3c9029566d92..6334ed16ed52 100644 --- a/libcxx/test/std/utilities/function.objects/func.search/func.search.default/implicit_ctad.pass.cpp +++ b/libcxx/test/std/utilities/function.objects/func.search/func.search.default/implicit_ctad.pass.cpp @@ -6,7 +6,7 @@ // //===----------------------------------------------------------------------===// -// UNSUPPORTED: c++98, c++03, c++11, c++14 +// UNSUPPORTED: c++03, c++11, c++14 // diff --git a/libcxx/test/std/utilities/function.objects/operations.implicit_ctad.pass.cpp b/libcxx/test/std/utilities/function.objects/operations.implicit_ctad.pass.cpp index 03c46d232c38..bb4fb4bf71c1 100644 --- a/libcxx/test/std/utilities/function.objects/operations.implicit_ctad.pass.cpp +++ b/libcxx/test/std/utilities/function.objects/operations.implicit_ctad.pass.cpp @@ -6,7 +6,7 @@ // //===----------------------------------------------------------------------===// -// UNSUPPORTED: c++98, c++03, c++11, c++14 +// UNSUPPORTED: c++03, c++11, c++14 // -- GitLab From 4351787fb650da6d1bfb8d6e58753c90dcd4c418 Mon Sep 17 00:00:00 2001 From: Matt Arsenault Date: Wed, 22 May 2024 11:02:20 +0200 Subject: [PATCH 087/452] AMDGPU: Fix redundant condition Fixes #93003 --- llvm/lib/Target/AMDGPU/SIISelLowering.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/llvm/lib/Target/AMDGPU/SIISelLowering.cpp b/llvm/lib/Target/AMDGPU/SIISelLowering.cpp index 45a16a14996e..7fe6c2d0db8f 100644 --- a/llvm/lib/Target/AMDGPU/SIISelLowering.cpp +++ b/llvm/lib/Target/AMDGPU/SIISelLowering.cpp @@ -7593,8 +7593,7 @@ static SDValue constructRetValue(SelectionDAG &DAG, MachineSDNode *Result, ? (ReqRetNumElts + 1) / 2 : ReqRetNumElts; - int MaskPopDwords = (!IsD16 || (IsD16 && Unpacked)) ? - DMaskPop : (DMaskPop + 1) / 2; + int MaskPopDwords = (!IsD16 || Unpacked) ? DMaskPop : (DMaskPop + 1) / 2; MVT DataDwordVT = NumDataDwords == 1 ? MVT::i32 : MVT::getVectorVT(MVT::i32, NumDataDwords); -- GitLab From 15710bbdadddbf03428fd16aed53e6be54960703 Mon Sep 17 00:00:00 2001 From: Kiran Chandramohan Date: Wed, 22 May 2024 10:21:46 +0100 Subject: [PATCH 088/452] [Flang][OpenMP] Re-enable tests on windows 1/n (#92904) Re-enable tests starting with a or b. --- flang/test/Semantics/OpenMP/allocate01.f90 | 2 -- flang/test/Semantics/OpenMP/allocate02.f90 | 2 -- flang/test/Semantics/OpenMP/allocate03.f90 | 2 -- flang/test/Semantics/OpenMP/allocate04.f90 | 2 -- flang/test/Semantics/OpenMP/allocate05.f90 | 2 -- flang/test/Semantics/OpenMP/allocate06.f90 | 2 -- flang/test/Semantics/OpenMP/allocate07.f90 | 2 -- flang/test/Semantics/OpenMP/allocate08.f90 | 2 -- flang/test/Semantics/OpenMP/allocate09.f90 | 2 -- flang/test/Semantics/OpenMP/allocators01.f90 | 2 -- flang/test/Semantics/OpenMP/allocators02.f90 | 2 -- flang/test/Semantics/OpenMP/allocators03.f90 | 2 -- flang/test/Semantics/OpenMP/allocators04.f90 | 2 -- flang/test/Semantics/OpenMP/allocators05.f90 | 2 -- flang/test/Semantics/OpenMP/allocators06.f90 | 2 -- flang/test/Semantics/OpenMP/atomic.f90 | 2 -- flang/test/Semantics/OpenMP/atomic01.f90 | 2 -- flang/test/Semantics/OpenMP/atomic02.f90 | 2 -- flang/test/Semantics/OpenMP/atomic03.f90 | 2 -- flang/test/Semantics/OpenMP/atomic04.f90 | 2 -- flang/test/Semantics/OpenMP/atomic05.f90 | 2 -- flang/test/Semantics/OpenMP/barrier.f90 | 2 -- 22 files changed, 44 deletions(-) diff --git a/flang/test/Semantics/OpenMP/allocate01.f90 b/flang/test/Semantics/OpenMP/allocate01.f90 index a3d5fb5f90cd..6ccb8bb09e83 100644 --- a/flang/test/Semantics/OpenMP/allocate01.f90 +++ b/flang/test/Semantics/OpenMP/allocate01.f90 @@ -1,5 +1,3 @@ -! UNSUPPORTED: system-windows -! Marking as unsupported due to suspected long runtime on Windows ! REQUIRES: openmp_runtime ! RUN: %python %S/../test_errors.py %s %flang_fc1 %openmp_flags diff --git a/flang/test/Semantics/OpenMP/allocate02.f90 b/flang/test/Semantics/OpenMP/allocate02.f90 index b9bfdbe55aa2..8f0579e810bb 100644 --- a/flang/test/Semantics/OpenMP/allocate02.f90 +++ b/flang/test/Semantics/OpenMP/allocate02.f90 @@ -1,5 +1,3 @@ -! UNSUPPORTED: system-windows -! Marking as unsupported due to suspected long runtime on Windows ! REQUIRES: openmp_runtime ! RUN: %python %S/../test_errors.py %s %flang_fc1 %openmp_flags diff --git a/flang/test/Semantics/OpenMP/allocate03.f90 b/flang/test/Semantics/OpenMP/allocate03.f90 index ce577c857985..e35115f3897c 100644 --- a/flang/test/Semantics/OpenMP/allocate03.f90 +++ b/flang/test/Semantics/OpenMP/allocate03.f90 @@ -1,5 +1,3 @@ -! UNSUPPORTED: system-windows -! Marking as unsupported due to suspected long runtime on Windows ! REQUIRES: openmp_runtime ! RUN: %python %S/../test_errors.py %s %flang_fc1 %openmp_flags diff --git a/flang/test/Semantics/OpenMP/allocate04.f90 b/flang/test/Semantics/OpenMP/allocate04.f90 index 37f180cc16aa..ea89d9446cc1 100644 --- a/flang/test/Semantics/OpenMP/allocate04.f90 +++ b/flang/test/Semantics/OpenMP/allocate04.f90 @@ -1,5 +1,3 @@ -! UNSUPPORTED: system-windows -! Marking as unsupported due to suspected long runtime on Windows ! REQUIRES: openmp_runtime ! RUN: %python %S/../test_errors.py %s %flang_fc1 %openmp_flags diff --git a/flang/test/Semantics/OpenMP/allocate05.f90 b/flang/test/Semantics/OpenMP/allocate05.f90 index c4e0ace988bd..a787e8bb32a4 100644 --- a/flang/test/Semantics/OpenMP/allocate05.f90 +++ b/flang/test/Semantics/OpenMP/allocate05.f90 @@ -1,5 +1,3 @@ -! UNSUPPORTED: system-windows -! Marking as unsupported due to suspected long runtime on Windows ! REQUIRES: openmp_runtime ! RUN: %python %S/../test_errors.py %s %flang_fc1 %openmp_flags diff --git a/flang/test/Semantics/OpenMP/allocate06.f90 b/flang/test/Semantics/OpenMP/allocate06.f90 index e25b4c4decd5..e14134cd0730 100644 --- a/flang/test/Semantics/OpenMP/allocate06.f90 +++ b/flang/test/Semantics/OpenMP/allocate06.f90 @@ -1,5 +1,3 @@ -! UNSUPPORTED: system-windows -! Marking as unsupported due to suspected long runtime on Windows ! REQUIRES: openmp_runtime ! RUN: %python %S/../test_errors.py %s %flang_fc1 %openmp_flags diff --git a/flang/test/Semantics/OpenMP/allocate07.f90 b/flang/test/Semantics/OpenMP/allocate07.f90 index 2b0f17647b3c..396df598b252 100644 --- a/flang/test/Semantics/OpenMP/allocate07.f90 +++ b/flang/test/Semantics/OpenMP/allocate07.f90 @@ -1,5 +1,3 @@ -! UNSUPPORTED: system-windows -! Marking as unsupported due to suspected long runtime on Windows ! REQUIRES: openmp_runtime ! RUN: %python %S/../test_errors.py %s %flang_fc1 %openmp_flags diff --git a/flang/test/Semantics/OpenMP/allocate08.f90 b/flang/test/Semantics/OpenMP/allocate08.f90 index 82aa11d69cfc..fc950ea4fca3 100644 --- a/flang/test/Semantics/OpenMP/allocate08.f90 +++ b/flang/test/Semantics/OpenMP/allocate08.f90 @@ -1,5 +1,3 @@ -! UNSUPPORTED: system-windows -! Marking as unsupported due to suspected long runtime on Windows ! REQUIRES: openmp_runtime ! RUN: %python %S/../test_errors.py %s %flang_fc1 %openmp_flags diff --git a/flang/test/Semantics/OpenMP/allocate09.f90 b/flang/test/Semantics/OpenMP/allocate09.f90 index 3664c34c7e43..0f93a340fe1e 100644 --- a/flang/test/Semantics/OpenMP/allocate09.f90 +++ b/flang/test/Semantics/OpenMP/allocate09.f90 @@ -1,5 +1,3 @@ -! UNSUPPORTED: system-windows -! Marking as unsupported due to suspected long runtime on Windows ! REQUIRES: openmp_runtime ! RUN: %python %S/../test_errors.py %s %flang_fc1 %openmp_flags diff --git a/flang/test/Semantics/OpenMP/allocators01.f90 b/flang/test/Semantics/OpenMP/allocators01.f90 index f10db35f96d9..c75c522ecae1 100644 --- a/flang/test/Semantics/OpenMP/allocators01.f90 +++ b/flang/test/Semantics/OpenMP/allocators01.f90 @@ -1,5 +1,3 @@ -! UNSUPPORTED: system-windows -! Marking as unsupported due to suspected long runtime on Windows ! REQUIRES: openmp_runtime ! RUN: %python %S/../test_errors.py %s %flang_fc1 %openmp_flags diff --git a/flang/test/Semantics/OpenMP/allocators02.f90 b/flang/test/Semantics/OpenMP/allocators02.f90 index 7f8fa3600277..8055d21c6809 100644 --- a/flang/test/Semantics/OpenMP/allocators02.f90 +++ b/flang/test/Semantics/OpenMP/allocators02.f90 @@ -1,5 +1,3 @@ -! UNSUPPORTED: system-windows -! Marking as unsupported due to suspected long runtime on Windows ! REQUIRES: openmp_runtime ! RUN: %python %S/../test_errors.py %s %flang_fc1 %openmp_flags diff --git a/flang/test/Semantics/OpenMP/allocators03.f90 b/flang/test/Semantics/OpenMP/allocators03.f90 index 050cc2051c99..03cff1b1e991 100644 --- a/flang/test/Semantics/OpenMP/allocators03.f90 +++ b/flang/test/Semantics/OpenMP/allocators03.f90 @@ -1,5 +1,3 @@ -! UNSUPPORTED: system-windows -! Marking as unsupported due to suspected long runtime on Windows ! REQUIRES: openmp_runtime ! RUN: %python %S/../test_errors.py %s %flang_fc1 %openmp_flags diff --git a/flang/test/Semantics/OpenMP/allocators04.f90 b/flang/test/Semantics/OpenMP/allocators04.f90 index 3c84030c4e39..1d2e96443a9d 100644 --- a/flang/test/Semantics/OpenMP/allocators04.f90 +++ b/flang/test/Semantics/OpenMP/allocators04.f90 @@ -1,5 +1,3 @@ -! UNSUPPORTED: system-windows -! Marking as unsupported due to suspected long runtime on Windows ! REQUIRES: openmp_runtime ! RUN: %python %S/../test_errors.py %s %flang_fc1 %openmp_flags diff --git a/flang/test/Semantics/OpenMP/allocators05.f90 b/flang/test/Semantics/OpenMP/allocators05.f90 index 8fd80b033756..d0e11ca5874d 100644 --- a/flang/test/Semantics/OpenMP/allocators05.f90 +++ b/flang/test/Semantics/OpenMP/allocators05.f90 @@ -1,5 +1,3 @@ -! UNSUPPORTED: system-windows -! Marking as unsupported due to suspected long runtime on Windows ! REQUIRES: openmp_runtime ! RUN: %python %S/../test_errors.py %s %flang_fc1 %openmp_flags diff --git a/flang/test/Semantics/OpenMP/allocators06.f90 b/flang/test/Semantics/OpenMP/allocators06.f90 index 881182caa9b3..a975204c1133 100644 --- a/flang/test/Semantics/OpenMP/allocators06.f90 +++ b/flang/test/Semantics/OpenMP/allocators06.f90 @@ -1,5 +1,3 @@ -! UNSUPPORTED: system-windows -! Marking as unsupported due to suspected long runtime on Windows ! REQUIRES: openmp_runtime ! RUN: %python %S/../test_errors.py %s %flang_fc1 %openmp_flags diff --git a/flang/test/Semantics/OpenMP/atomic.f90 b/flang/test/Semantics/OpenMP/atomic.f90 index 2f270ce33338..44f06b7460bf 100644 --- a/flang/test/Semantics/OpenMP/atomic.f90 +++ b/flang/test/Semantics/OpenMP/atomic.f90 @@ -1,5 +1,3 @@ -! UNSUPPORTED: system-windows -! Marking as unsupported due to suspected long runtime on Windows ! RUN: %python %S/../test_errors.py %s %flang -fopenmp use omp_lib ! Check OpenMP 2.13.6 atomic Construct diff --git a/flang/test/Semantics/OpenMP/atomic01.f90 b/flang/test/Semantics/OpenMP/atomic01.f90 index 6ec94f3ff3a4..f0e1b47d2fa1 100644 --- a/flang/test/Semantics/OpenMP/atomic01.f90 +++ b/flang/test/Semantics/OpenMP/atomic01.f90 @@ -1,5 +1,3 @@ -! UNSUPPORTED: system-windows -! Marking as unsupported due to suspected long runtime on Windows ! REQUIRES: openmp_runtime ! RUN: %python %S/../test_errors.py %s %flang_fc1 %openmp_flags diff --git a/flang/test/Semantics/OpenMP/atomic02.f90 b/flang/test/Semantics/OpenMP/atomic02.f90 index 92f2c4b9d040..b823bc4c33b2 100644 --- a/flang/test/Semantics/OpenMP/atomic02.f90 +++ b/flang/test/Semantics/OpenMP/atomic02.f90 @@ -1,5 +1,3 @@ -! UNSUPPORTED: system-windows -! Marking as unsupported due to suspected long runtime on Windows ! REQUIRES: openmp_runtime ! RUN: %python %S/../test_errors.py %s %flang_fc1 %openmp_flags diff --git a/flang/test/Semantics/OpenMP/atomic03.f90 b/flang/test/Semantics/OpenMP/atomic03.f90 index 4cce71dba351..76367495b986 100644 --- a/flang/test/Semantics/OpenMP/atomic03.f90 +++ b/flang/test/Semantics/OpenMP/atomic03.f90 @@ -1,5 +1,3 @@ -! UNSUPPORTED: system-windows -! Marking as unsupported due to suspected long runtime on Windows ! REQUIRES: openmp_runtime ! RUN: %python %S/../test_errors.py %s %flang_fc1 %openmp_flags diff --git a/flang/test/Semantics/OpenMP/atomic04.f90 b/flang/test/Semantics/OpenMP/atomic04.f90 index c03b230c837a..a9644ad95aa3 100644 --- a/flang/test/Semantics/OpenMP/atomic04.f90 +++ b/flang/test/Semantics/OpenMP/atomic04.f90 @@ -1,5 +1,3 @@ -! UNSUPPORTED: system-windows -! Marking as unsupported due to suspected long runtime on Windows ! REQUIRES: openmp_runtime ! RUN: %python %S/../test_errors.py %s %flang_fc1 %openmp_flags diff --git a/flang/test/Semantics/OpenMP/atomic05.f90 b/flang/test/Semantics/OpenMP/atomic05.f90 index cfba33968213..2d9566463309 100644 --- a/flang/test/Semantics/OpenMP/atomic05.f90 +++ b/flang/test/Semantics/OpenMP/atomic05.f90 @@ -1,5 +1,3 @@ -! UNSUPPORTED: system-windows -! Marking as unsupported due to suspected long runtime on Windows ! REQUIRES: openmp_runtime ! RUN: %python %S/../test_errors.py %s %flang %openmp_flags diff --git a/flang/test/Semantics/OpenMP/barrier.f90 b/flang/test/Semantics/OpenMP/barrier.f90 index 5fc3f7f3bd70..1483fbd08f95 100644 --- a/flang/test/Semantics/OpenMP/barrier.f90 +++ b/flang/test/Semantics/OpenMP/barrier.f90 @@ -1,5 +1,3 @@ -! UNSUPPORTED: system-windows -! Marking as unsupported due to suspected long runtime on Windows ! RUN: %python %S/../test_errors.py %s %flang -fopenmp !$omp barrier -- GitLab From 91d415b8d94b15023e6c39d5376274a2b21ee448 Mon Sep 17 00:00:00 2001 From: Momchil Velikov Date: Wed, 22 May 2024 10:41:03 +0100 Subject: [PATCH 089/452] [Clang][AArch64][SVE] Allow write to SVE vector elements using the subscript operator (#91965) The patch at https://reviews.llvm.org/D122732 introduced using the array subscript operator for SVE vectors, however it also causes an ICE when the subscripting expression is used as an lvalue. This patches fixes the error. Lvalue subscripting expressions are emitted as LLVM IR `insertelement`. --- clang/lib/CodeGen/CGExpr.cpp | 2 +- clang/lib/Sema/SemaExpr.cpp | 2 +- .../aarch64-sve-vector-subscript-ops.c | 22 +++++++++++++++++++ 3 files changed, 24 insertions(+), 2 deletions(-) diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp index cd1c48b42038..6f9237e2067f 100644 --- a/clang/lib/CodeGen/CGExpr.cpp +++ b/clang/lib/CodeGen/CGExpr.cpp @@ -4180,7 +4180,7 @@ LValue CodeGenFunction::EmitArraySubscriptExpr(const ArraySubscriptExpr *E, // If the base is a vector type, then we are forming a vector element lvalue // with this subscript. - if (E->getBase()->getType()->isVectorType() && + if (E->getBase()->getType()->isSubscriptableVectorType() && !isa(E->getBase())) { // Emit the vector as an lvalue to get its address. LValue LHS = EmitLValue(E->getBase()); diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index f0ad3de31138..282508d489a5 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -5185,7 +5185,7 @@ Sema::CreateBuiltinArraySubscriptExpr(Expr *Base, SourceLocation LLoc, } // Perform default conversions. - if (!LHSExp->getType()->getAs()) { + if (!LHSExp->getType()->isSubscriptableVectorType()) { ExprResult Result = DefaultFunctionArrayLvalueConversion(LHSExp); if (Result.isInvalid()) return ExprError(); diff --git a/clang/test/CodeGen/aarch64-sve-vector-subscript-ops.c b/clang/test/CodeGen/aarch64-sve-vector-subscript-ops.c index fb60c6d100ce..52a05d010de9 100644 --- a/clang/test/CodeGen/aarch64-sve-vector-subscript-ops.c +++ b/clang/test/CodeGen/aarch64-sve-vector-subscript-ops.c @@ -88,3 +88,25 @@ float subscript_float32(svfloat32_t a, size_t b) { double subscript_float64(svfloat64_t a, size_t b) { return a[b]; } + +// CHECK-LABEL: @subscript_write_float32( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[VECINS:%.*]] = insertelement [[A:%.*]], float 1.000000e+00, i64 [[B:%.*]] +// CHECK-NEXT: ret [[VECINS]] +// +svfloat32_t subscript_write_float32(svfloat32_t a, size_t b) { + a[b] = 1.0f; + return a; +} + +// CHECK-LABEL: @subscript_read_write_float32( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[VECEXT:%.*]] = extractelement [[A:%.*]], i64 [[B:%.*]] +// CHECK-NEXT: [[ADD:%.*]] = fadd float [[VECEXT]], 1.000000e+00 +// CHECK-NEXT: [[VECINS:%.*]] = insertelement [[A]], float [[ADD]], i64 [[B]] +// CHECK-NEXT: ret [[VECINS]] +// +svfloat32_t subscript_read_write_float32(svfloat32_t a, size_t b) { + a[b] += 1.0f; + return a; +} -- GitLab From 758e1199f6dbcddc0a8d425753c56a42507dd313 Mon Sep 17 00:00:00 2001 From: Shengchen Kan Date: Mon, 20 May 2024 17:19:17 +0800 Subject: [PATCH 090/452] [X86] Simplify the code for EFLAGS copy lowering, NFCI 1. MF.begin() == MF.end() -> MF.empty() 2. Set FlagsKilled by API modifiesRegister 3. Utilize APIs in X86GenMnemonicTables.inc to check arithmetic op 4. Merge duplicated code for rewrite* 5. Clang format This is to address review comments in #91849 --- llvm/lib/Target/X86/X86FlagsCopyLowering.cpp | 500 ++++++------------- 1 file changed, 143 insertions(+), 357 deletions(-) diff --git a/llvm/lib/Target/X86/X86FlagsCopyLowering.cpp b/llvm/lib/Target/X86/X86FlagsCopyLowering.cpp index ea5ef5b5a602..80ff98b46617 100644 --- a/llvm/lib/Target/X86/X86FlagsCopyLowering.cpp +++ b/llvm/lib/Target/X86/X86FlagsCopyLowering.cpp @@ -73,7 +73,7 @@ using CondRegArray = std::array; class X86FlagsCopyLoweringPass : public MachineFunctionPass { public: - X86FlagsCopyLoweringPass() : MachineFunctionPass(ID) { } + X86FlagsCopyLoweringPass() : MachineFunctionPass(ID) {} StringRef getPassName() const override { return "X86 EFLAGS copy lowering"; } bool runOnMachineFunction(MachineFunction &MF) override; @@ -102,32 +102,14 @@ private: void insertTest(MachineBasicBlock &MBB, MachineBasicBlock::iterator Pos, const DebugLoc &Loc, unsigned Reg); - void rewriteArithmetic(MachineBasicBlock &TestMBB, - MachineBasicBlock::iterator TestPos, - const DebugLoc &TestLoc, MachineInstr &MI, - MachineOperand &FlagUse, CondRegArray &CondRegs); - void rewriteCMov(MachineBasicBlock &TestMBB, - MachineBasicBlock::iterator TestPos, const DebugLoc &TestLoc, - MachineInstr &CMovI, MachineOperand &FlagUse, - CondRegArray &CondRegs); - void rewriteFCMov(MachineBasicBlock &TestMBB, - MachineBasicBlock::iterator TestPos, - const DebugLoc &TestLoc, MachineInstr &CMovI, - MachineOperand &FlagUse, CondRegArray &CondRegs); - void rewriteCondJmp(MachineBasicBlock &TestMBB, - MachineBasicBlock::iterator TestPos, - const DebugLoc &TestLoc, MachineInstr &JmpI, - CondRegArray &CondRegs); - void rewriteCopy(MachineInstr &MI, MachineOperand &FlagUse, - MachineInstr &CopyDefI); - void rewriteSetCC(MachineBasicBlock &TestMBB, - MachineBasicBlock::iterator TestPos, - const DebugLoc &TestLoc, MachineInstr &SetCCI, - MachineOperand &FlagUse, CondRegArray &CondRegs); - void rewriteCCMP(MachineBasicBlock &TestMBB, - MachineBasicBlock::iterator TestPos, const DebugLoc &TestLoc, - MachineInstr &CMovI, MachineOperand &FlagUse, - CondRegArray &CondRegs); + void rewriteSetCC(MachineBasicBlock &MBB, MachineBasicBlock::iterator Pos, + const DebugLoc &Loc, MachineInstr &MI, + CondRegArray &CondRegs); + void rewriteArithmetic(MachineBasicBlock &MBB, + MachineBasicBlock::iterator Pos, const DebugLoc &Loc, + MachineInstr &MI, CondRegArray &CondRegs); + void rewriteMI(MachineBasicBlock &MBB, MachineBasicBlock::iterator Pos, + const DebugLoc &Loc, MachineInstr &MI, CondRegArray &CondRegs); }; } // end anonymous namespace @@ -148,85 +130,9 @@ void X86FlagsCopyLoweringPass::getAnalysisUsage(AnalysisUsage &AU) const { MachineFunctionPass::getAnalysisUsage(AU); } -namespace { -/// An enumeration of the arithmetic instruction mnemonics which have -/// interesting flag semantics. -/// -/// We can map instruction opcodes into these mnemonics to make it easy to -/// dispatch with specific functionality. -enum class FlagArithMnemonic { - ADC, - RCL, - RCR, - SBB, - SETB, -}; -} // namespace - -static FlagArithMnemonic getMnemonicFromOpcode(unsigned Opcode) { - switch (Opcode) { - default: - report_fatal_error("No support for lowering a copy into EFLAGS when used " - "by this instruction!"); - -#define CASE_ND(OP) \ - case X86::OP: \ - case X86::OP##_ND: - -#define LLVM_EXPAND_INSTR_SIZES(MNEMONIC, SUFFIX) \ - CASE_ND(MNEMONIC##8##SUFFIX) \ - CASE_ND(MNEMONIC##16##SUFFIX) \ - CASE_ND(MNEMONIC##32##SUFFIX) \ - CASE_ND(MNEMONIC##64##SUFFIX) - -#define LLVM_EXPAND_ADC_SBB_INSTR(MNEMONIC) \ - LLVM_EXPAND_INSTR_SIZES(MNEMONIC, rr) \ - LLVM_EXPAND_INSTR_SIZES(MNEMONIC, rm) \ - LLVM_EXPAND_INSTR_SIZES(MNEMONIC, mr) \ - CASE_ND(MNEMONIC##8ri) \ - CASE_ND(MNEMONIC##16ri8) \ - CASE_ND(MNEMONIC##32ri8) \ - CASE_ND(MNEMONIC##64ri8) \ - CASE_ND(MNEMONIC##16ri) \ - CASE_ND(MNEMONIC##32ri) \ - CASE_ND(MNEMONIC##64ri32) \ - CASE_ND(MNEMONIC##8mi) \ - CASE_ND(MNEMONIC##16mi8) \ - CASE_ND(MNEMONIC##32mi8) \ - CASE_ND(MNEMONIC##64mi8) \ - CASE_ND(MNEMONIC##16mi) \ - CASE_ND(MNEMONIC##32mi) \ - CASE_ND(MNEMONIC##64mi32) \ - case X86::MNEMONIC##8i8: \ - case X86::MNEMONIC##16i16: \ - case X86::MNEMONIC##32i32: \ - case X86::MNEMONIC##64i32: - - LLVM_EXPAND_ADC_SBB_INSTR(ADC) - return FlagArithMnemonic::ADC; - - LLVM_EXPAND_ADC_SBB_INSTR(SBB) - return FlagArithMnemonic::SBB; - -#undef LLVM_EXPAND_ADC_SBB_INSTR - - LLVM_EXPAND_INSTR_SIZES(RCL, rCL) - LLVM_EXPAND_INSTR_SIZES(RCL, r1) - LLVM_EXPAND_INSTR_SIZES(RCL, ri) - return FlagArithMnemonic::RCL; - - LLVM_EXPAND_INSTR_SIZES(RCR, rCL) - LLVM_EXPAND_INSTR_SIZES(RCR, r1) - LLVM_EXPAND_INSTR_SIZES(RCR, ri) - return FlagArithMnemonic::RCR; - -#undef LLVM_EXPAND_INSTR_SIZES -#undef CASE_ND - - case X86::SETB_C32r: - case X86::SETB_C64r: - return FlagArithMnemonic::SETB; - } +static bool isArithmeticOp(unsigned Opc) { + return X86::isADC(Opc) || X86::isSBB(Opc) || X86::isRCL(Opc) || + X86::isRCR(Opc) || (Opc == X86::SETB_C32r || Opc == X86::SETB_C64r); } static MachineBasicBlock &splitBlock(MachineBasicBlock &MBB, @@ -329,28 +235,6 @@ static MachineBasicBlock &splitBlock(MachineBasicBlock &MBB, return NewMBB; } -static X86::CondCode getCondFromFCMOV(unsigned Opcode) { - switch (Opcode) { - default: return X86::COND_INVALID; - case X86::CMOVBE_Fp32: case X86::CMOVBE_Fp64: case X86::CMOVBE_Fp80: - return X86::COND_BE; - case X86::CMOVB_Fp32: case X86::CMOVB_Fp64: case X86::CMOVB_Fp80: - return X86::COND_B; - case X86::CMOVE_Fp32: case X86::CMOVE_Fp64: case X86::CMOVE_Fp80: - return X86::COND_E; - case X86::CMOVNBE_Fp32: case X86::CMOVNBE_Fp64: case X86::CMOVNBE_Fp80: - return X86::COND_A; - case X86::CMOVNB_Fp32: case X86::CMOVNB_Fp64: case X86::CMOVNB_Fp80: - return X86::COND_AE; - case X86::CMOVNE_Fp32: case X86::CMOVNE_Fp64: case X86::CMOVNE_Fp80: - return X86::COND_NE; - case X86::CMOVNP_Fp32: case X86::CMOVNP_Fp64: case X86::CMOVNP_Fp80: - return X86::COND_NP; - case X86::CMOVP_Fp32: case X86::CMOVP_Fp64: case X86::CMOVP_Fp80: - return X86::COND_P; - } -} - bool X86FlagsCopyLoweringPass::runOnMachineFunction(MachineFunction &MF) { LLVM_DEBUG(dbgs() << "********** " << getPassName() << " : " << MF.getName() << " **********\n"); @@ -362,7 +246,7 @@ bool X86FlagsCopyLoweringPass::runOnMachineFunction(MachineFunction &MF) { MDT = &getAnalysis(); PromoteRC = &X86::GR8RegClass; - if (MF.begin() == MF.end()) + if (MF.empty()) // Nothing to do for a degenerate empty function... return false; @@ -569,20 +453,12 @@ bool X86FlagsCopyLoweringPass::runOnMachineFunction(MachineFunction &MF) { MachineOperand *FlagUse = MI.findRegisterUseOperand(X86::EFLAGS, /*TRI=*/nullptr); - if (!FlagUse) { - if (MI.findRegisterDefOperand(X86::EFLAGS, /*TRI=*/nullptr)) { - // If EFLAGS are defined, it's as-if they were killed. We can stop - // scanning here. - // - // NB!!! Many instructions only modify some flags. LLVM currently - // models this as clobbering all flags, but if that ever changes - // this will need to be carefully updated to handle that more - // complex logic. - FlagsKilled = true; - break; - } + FlagsKilled = MI.modifiesRegister(X86::EFLAGS, TRI); + + if (!FlagUse && FlagsKilled) + break; + else if (!FlagUse) continue; - } LLVM_DEBUG(dbgs() << " Rewriting use: "; MI.dump()); @@ -604,40 +480,23 @@ bool X86FlagsCopyLoweringPass::runOnMachineFunction(MachineFunction &MF) { JmpIs.push_back(&*JmpIt); ++JmpIt; } while (JmpIt != UseMBB.instr_end() && - X86::getCondFromBranch(*JmpIt) != - X86::COND_INVALID); + X86::getCondFromBranch(*JmpIt) != X86::COND_INVALID); break; } // Otherwise we can just rewrite in-place. - if (X86::getCondFromCMov(MI) != X86::COND_INVALID || - X86::getCondFromCFCMov(MI) != X86::COND_INVALID) { - rewriteCMov(*TestMBB, TestPos, TestLoc, MI, *FlagUse, CondRegs); - } else if (getCondFromFCMOV(MI.getOpcode()) != X86::COND_INVALID) { - rewriteFCMov(*TestMBB, TestPos, TestLoc, MI, *FlagUse, CondRegs); - } else if (X86::getCondFromSETCC(MI) != X86::COND_INVALID) { - rewriteSetCC(*TestMBB, TestPos, TestLoc, MI, *FlagUse, CondRegs); - } else if (X86::getCondFromCCMP(MI) != X86::COND_INVALID) { - rewriteCCMP(*TestMBB, TestPos, TestLoc, MI, *FlagUse, CondRegs); - FlagsKilled = true; - } else if (MI.getOpcode() == TargetOpcode::COPY) { - rewriteCopy(MI, *FlagUse, CopyDefI); + unsigned Opc = MI.getOpcode(); + if (Opc == TargetOpcode::COPY) { + // Just replace this copy with the original copy def. + MRI->replaceRegWith(MI.getOperand(0).getReg(), + CopyDefI.getOperand(0).getReg()); + MI.eraseFromParent(); + } else if (X86::isSETCC(Opc)) { + rewriteSetCC(*TestMBB, TestPos, TestLoc, MI, CondRegs); + } else if (isArithmeticOp(Opc)) { + rewriteArithmetic(*TestMBB, TestPos, TestLoc, MI, CondRegs); } else { - // We assume all other instructions that use flags also def them. - assert(MI.findRegisterDefOperand(X86::EFLAGS, /*TRI=*/nullptr) && - "Expected a def of EFLAGS for this instruction!"); - - // NB!!! Several arithmetic instructions only *partially* update - // flags. Theoretically, we could generate MI code sequences that - // would rely on this fact and observe different flags independently. - // But currently LLVM models all of these instructions as clobbering - // all the flags in an undef way. We rely on that to simplify the - // logic. - FlagsKilled = true; - - // Generically handle remaining uses as arithmetic instructions. - rewriteArithmetic(*TestMBB, TestPos, TestLoc, MI, *FlagUse, - CondRegs); + rewriteMI(*TestMBB, TestPos, TestLoc, MI, CondRegs); } // If this was the last use of the flags, we're done. @@ -702,7 +561,7 @@ bool X86FlagsCopyLoweringPass::runOnMachineFunction(MachineFunction &MF) { else LastJmpMBB = JmpI->getParent(); - rewriteCondJmp(*TestMBB, TestPos, TestLoc, *JmpI, CondRegs); + rewriteMI(*TestMBB, TestPos, TestLoc, *JmpI, CondRegs); } // FIXME: Mark the last use of EFLAGS before the copy's def as a kill if @@ -753,8 +612,8 @@ Register X86FlagsCopyLoweringPass::promoteCondToReg( MachineBasicBlock &TestMBB, MachineBasicBlock::iterator TestPos, const DebugLoc &TestLoc, X86::CondCode Cond) { Register Reg = MRI->createVirtualRegister(PromoteRC); - auto SetI = BuildMI(TestMBB, TestPos, TestLoc, - TII->get(X86::SETCCr), Reg).addImm(Cond); + auto SetI = BuildMI(TestMBB, TestPos, TestLoc, TII->get(X86::SETCCr), Reg) + .addImm(Cond); (void)SetI; LLVM_DEBUG(dbgs() << " save cond: "; SetI->dump()); ++NumSetCCsInserted; @@ -785,43 +644,66 @@ void X86FlagsCopyLoweringPass::insertTest(MachineBasicBlock &MBB, ++NumTestsInserted; } -void X86FlagsCopyLoweringPass::rewriteArithmetic( - MachineBasicBlock &TestMBB, MachineBasicBlock::iterator TestPos, - const DebugLoc &TestLoc, MachineInstr &MI, MachineOperand &FlagUse, - CondRegArray &CondRegs) { - // Arithmetic is either reading CF or OF. Figure out which condition we need - // to preserve in a register. - X86::CondCode Cond = X86::COND_INVALID; +void X86FlagsCopyLoweringPass::rewriteSetCC(MachineBasicBlock &MBB, + MachineBasicBlock::iterator Pos, + const DebugLoc &Loc, + MachineInstr &MI, + CondRegArray &CondRegs) { + X86::CondCode Cond = X86::getCondFromSETCC(MI); + // Note that we can't usefully rewrite this to the inverse without complex + // analysis of the users of the setCC. Largely we rely on duplicates which + // could have been avoided already being avoided here. + unsigned &CondReg = CondRegs[Cond]; + if (!CondReg) + CondReg = promoteCondToReg(MBB, Pos, Loc, Cond); - // The addend to use to reset CF or OF when added to the flag value. - int Addend = 0; - - switch (getMnemonicFromOpcode(MI.getOpcode())) { - case FlagArithMnemonic::ADC: - case FlagArithMnemonic::RCL: - case FlagArithMnemonic::RCR: - case FlagArithMnemonic::SBB: - case FlagArithMnemonic::SETB: - Cond = X86::COND_B; // CF == 1 - // Set up an addend that when one is added will need a carry due to not - // having a higher bit available. - Addend = 255; - break; + // Rewriting a register def is trivial: we just replace the register and + // remove the setcc. + if (!MI.mayStore()) { + assert(MI.getOperand(0).isReg() && + "Cannot have a non-register defined operand to SETcc!"); + Register OldReg = MI.getOperand(0).getReg(); + // Drop Kill flags on the old register before replacing. CondReg may have + // a longer live range. + MRI->clearKillFlags(OldReg); + MRI->replaceRegWith(OldReg, CondReg); + MI.eraseFromParent(); + return; } + // Otherwise, we need to emit a store. + auto MIB = BuildMI(*MI.getParent(), MI.getIterator(), MI.getDebugLoc(), + TII->get(X86::MOV8mr)); + // Copy the address operands. + for (int i = 0; i < X86::AddrNumOperands; ++i) + MIB.add(MI.getOperand(i)); + + MIB.addReg(CondReg); + MIB.setMemRefs(MI.memoperands()); + MI.eraseFromParent(); +} + +void X86FlagsCopyLoweringPass::rewriteArithmetic( + MachineBasicBlock &MBB, MachineBasicBlock::iterator Pos, + const DebugLoc &Loc, MachineInstr &MI, CondRegArray &CondRegs) { + // Arithmetic is either reading CF or OF. + X86::CondCode Cond = X86::COND_B; // CF == 1 + // The addend to use to reset CF or OF when added to the flag value. + // Set up an addend that when one is added will need a carry due to not + // having a higher bit available. + int Addend = 255; + // Now get a register that contains the value of the flag input to the // arithmetic. We require exactly this flag to simplify the arithmetic // required to materialize it back into the flag. unsigned &CondReg = CondRegs[Cond]; if (!CondReg) - CondReg = promoteCondToReg(TestMBB, TestPos, TestLoc, Cond); - - MachineBasicBlock &MBB = *MI.getParent(); + CondReg = promoteCondToReg(MBB, Pos, Loc, Cond); // Insert an instruction that will set the flag back to the desired value. Register TmpReg = MRI->createVirtualRegister(PromoteRC); auto AddI = - BuildMI(MBB, MI.getIterator(), MI.getDebugLoc(), + BuildMI(*MI.getParent(), MI.getIterator(), MI.getDebugLoc(), TII->get(Subtarget->hasNDD() ? X86::ADD8ri_ND : X86::ADD8ri)) .addDef(TmpReg, RegState::Dead) .addReg(CondReg) @@ -829,177 +711,81 @@ void X86FlagsCopyLoweringPass::rewriteArithmetic( (void)AddI; LLVM_DEBUG(dbgs() << " add cond: "; AddI->dump()); ++NumAddsInserted; - FlagUse.setIsKill(true); + MI.findRegisterUseOperand(X86::EFLAGS, /*TRI=*/nullptr)->setIsKill(true); } -void X86FlagsCopyLoweringPass::rewriteCMov(MachineBasicBlock &TestMBB, - MachineBasicBlock::iterator TestPos, - const DebugLoc &TestLoc, - MachineInstr &CMovI, - MachineOperand &FlagUse, - CondRegArray &CondRegs) { - // First get the register containing this specific condition. - X86::CondCode Cond = X86::getCondFromCMov(CMovI) == X86::COND_INVALID - ? X86::getCondFromCFCMov(CMovI) - : X86::getCondFromCMov(CMovI); - unsigned CondReg; - bool Inverted; - std::tie(CondReg, Inverted) = - getCondOrInverseInReg(TestMBB, TestPos, TestLoc, Cond, CondRegs); - - MachineBasicBlock &MBB = *CMovI.getParent(); +static X86::CondCode getImplicitCondFromMI(unsigned Opc) { +#define FROM_TO(A, B) \ + case X86::CMOV##A##_Fp32: \ + case X86::CMOV##A##_Fp64: \ + case X86::CMOV##A##_Fp80: \ + return X86::COND_##B; - // Insert a direct test of the saved register. - insertTest(MBB, CMovI.getIterator(), CMovI.getDebugLoc(), CondReg); - - // Rewrite the CMov to use the !ZF flag from the test, and then kill its use - // of the flags afterward. - CMovI.getOperand(CMovI.getDesc().getNumOperands() - 1) - .setImm(Inverted ? X86::COND_E : X86::COND_NE); - FlagUse.setIsKill(true); - LLVM_DEBUG(dbgs() << " fixed cmov: "; CMovI.dump()); + switch (Opc) { + default: + return X86::COND_INVALID; + FROM_TO(B, B) + FROM_TO(E, E) + FROM_TO(P, P) + FROM_TO(BE, BE) + FROM_TO(NB, AE) + FROM_TO(NE, NE) + FROM_TO(NP, NP) + FROM_TO(NBE, A) + } +#undef FROM_TO } -void X86FlagsCopyLoweringPass::rewriteFCMov(MachineBasicBlock &TestMBB, - MachineBasicBlock::iterator TestPos, - const DebugLoc &TestLoc, - MachineInstr &CMovI, - MachineOperand &FlagUse, - CondRegArray &CondRegs) { - // First get the register containing this specific condition. - X86::CondCode Cond = getCondFromFCMOV(CMovI.getOpcode()); - unsigned CondReg; - bool Inverted; - std::tie(CondReg, Inverted) = - getCondOrInverseInReg(TestMBB, TestPos, TestLoc, Cond, CondRegs); - - MachineBasicBlock &MBB = *CMovI.getParent(); - - // Insert a direct test of the saved register. - insertTest(MBB, CMovI.getIterator(), CMovI.getDebugLoc(), CondReg); - - auto getFCMOVOpcode = [](unsigned Opcode, bool Inverted) { - switch (Opcode) { - default: llvm_unreachable("Unexpected opcode!"); - case X86::CMOVBE_Fp32: case X86::CMOVNBE_Fp32: - case X86::CMOVB_Fp32: case X86::CMOVNB_Fp32: - case X86::CMOVE_Fp32: case X86::CMOVNE_Fp32: - case X86::CMOVP_Fp32: case X86::CMOVNP_Fp32: - return Inverted ? X86::CMOVE_Fp32 : X86::CMOVNE_Fp32; - case X86::CMOVBE_Fp64: case X86::CMOVNBE_Fp64: - case X86::CMOVB_Fp64: case X86::CMOVNB_Fp64: - case X86::CMOVE_Fp64: case X86::CMOVNE_Fp64: - case X86::CMOVP_Fp64: case X86::CMOVNP_Fp64: - return Inverted ? X86::CMOVE_Fp64 : X86::CMOVNE_Fp64; - case X86::CMOVBE_Fp80: case X86::CMOVNBE_Fp80: - case X86::CMOVB_Fp80: case X86::CMOVNB_Fp80: - case X86::CMOVE_Fp80: case X86::CMOVNE_Fp80: - case X86::CMOVP_Fp80: case X86::CMOVNP_Fp80: - return Inverted ? X86::CMOVE_Fp80 : X86::CMOVNE_Fp80; - } - }; - - // Rewrite the CMov to use the !ZF flag from the test. - CMovI.setDesc(TII->get(getFCMOVOpcode(CMovI.getOpcode(), Inverted))); - FlagUse.setIsKill(true); - LLVM_DEBUG(dbgs() << " fixed fcmov: "; CMovI.dump()); +static unsigned getOpcodeWithCC(unsigned Opc, X86::CondCode CC) { + assert((CC == X86::COND_E || CC == X86::COND_NE) && "Unexpected CC"); +#define CASE(A) \ + case X86::CMOVB_##A: \ + case X86::CMOVE_##A: \ + case X86::CMOVP_##A: \ + case X86::CMOVBE_##A: \ + case X86::CMOVNB_##A: \ + case X86::CMOVNE_##A: \ + case X86::CMOVNP_##A: \ + case X86::CMOVNBE_##A: \ + return (CC == X86::COND_E) ? X86::CMOVE_##A : X86::CMOVNE_##A; + switch (Opc) { + default: + llvm_unreachable("Unexpected opcode"); + CASE(Fp32) + CASE(Fp64) + CASE(Fp80) + } +#undef CASE } -void X86FlagsCopyLoweringPass::rewriteCondJmp( - MachineBasicBlock &TestMBB, MachineBasicBlock::iterator TestPos, - const DebugLoc &TestLoc, MachineInstr &JmpI, CondRegArray &CondRegs) { +void X86FlagsCopyLoweringPass::rewriteMI(MachineBasicBlock &MBB, + MachineBasicBlock::iterator Pos, + const DebugLoc &Loc, MachineInstr &MI, + CondRegArray &CondRegs) { // First get the register containing this specific condition. - X86::CondCode Cond = X86::getCondFromBranch(JmpI); + bool IsImplicitCC = false; + X86::CondCode CC = X86::getCondFromMI(MI); + if (CC == X86::COND_INVALID) { + CC = getImplicitCondFromMI(MI.getOpcode()); + IsImplicitCC = true; + } + assert(CC != X86::COND_INVALID && "Unknown EFLAG user!"); unsigned CondReg; bool Inverted; std::tie(CondReg, Inverted) = - getCondOrInverseInReg(TestMBB, TestPos, TestLoc, Cond, CondRegs); - - MachineBasicBlock &JmpMBB = *JmpI.getParent(); + getCondOrInverseInReg(MBB, Pos, Loc, CC, CondRegs); // Insert a direct test of the saved register. - insertTest(JmpMBB, JmpI.getIterator(), JmpI.getDebugLoc(), CondReg); - - // Rewrite the jump to use the !ZF flag from the test, and kill its use of - // flags afterward. - JmpI.getOperand(1).setImm(Inverted ? X86::COND_E : X86::COND_NE); - JmpI.findRegisterUseOperand(X86::EFLAGS, /*TRI=*/nullptr)->setIsKill(true); - LLVM_DEBUG(dbgs() << " fixed jCC: "; JmpI.dump()); -} - -void X86FlagsCopyLoweringPass::rewriteCopy(MachineInstr &MI, - MachineOperand &FlagUse, - MachineInstr &CopyDefI) { - // Just replace this copy with the original copy def. - MRI->replaceRegWith(MI.getOperand(0).getReg(), - CopyDefI.getOperand(0).getReg()); - MI.eraseFromParent(); -} - -void X86FlagsCopyLoweringPass::rewriteSetCC(MachineBasicBlock &TestMBB, - MachineBasicBlock::iterator TestPos, - const DebugLoc &TestLoc, - MachineInstr &SetCCI, - MachineOperand &FlagUse, - CondRegArray &CondRegs) { - X86::CondCode Cond = X86::getCondFromSETCC(SetCCI); - // Note that we can't usefully rewrite this to the inverse without complex - // analysis of the users of the setCC. Largely we rely on duplicates which - // could have been avoided already being avoided here. - unsigned &CondReg = CondRegs[Cond]; - if (!CondReg) - CondReg = promoteCondToReg(TestMBB, TestPos, TestLoc, Cond); - - // Rewriting a register def is trivial: we just replace the register and - // remove the setcc. - if (!SetCCI.mayStore()) { - assert(SetCCI.getOperand(0).isReg() && - "Cannot have a non-register defined operand to SETcc!"); - Register OldReg = SetCCI.getOperand(0).getReg(); - // Drop Kill flags on the old register before replacing. CondReg may have - // a longer live range. - MRI->clearKillFlags(OldReg); - MRI->replaceRegWith(OldReg, CondReg); - SetCCI.eraseFromParent(); - return; - } + insertTest(*MI.getParent(), MI.getIterator(), MI.getDebugLoc(), CondReg); - // Otherwise, we need to emit a store. - auto MIB = BuildMI(*SetCCI.getParent(), SetCCI.getIterator(), - SetCCI.getDebugLoc(), TII->get(X86::MOV8mr)); - // Copy the address operands. - for (int i = 0; i < X86::AddrNumOperands; ++i) - MIB.add(SetCCI.getOperand(i)); - - MIB.addReg(CondReg); - - MIB.setMemRefs(SetCCI.memoperands()); - - SetCCI.eraseFromParent(); -} - -void X86FlagsCopyLoweringPass::rewriteCCMP(MachineBasicBlock &TestMBB, - MachineBasicBlock::iterator TestPos, - const DebugLoc &TestLoc, - MachineInstr &CCMPI, - MachineOperand &FlagUse, - CondRegArray &CondRegs) { - // First get the register containing this specific condition. - X86::CondCode Cond = X86::getCondFromCCMP(CCMPI); - unsigned CondReg; - bool Inverted; - std::tie(CondReg, Inverted) = - getCondOrInverseInReg(TestMBB, TestPos, TestLoc, Cond, CondRegs); - - MachineBasicBlock &MBB = *CCMPI.getParent(); + // Rewrite the instruction to use the !ZF flag from the test, and then kill + // its use of the flags afterward. + X86::CondCode NewCC = Inverted ? X86::COND_E : X86::COND_NE; + if (IsImplicitCC) + MI.setDesc(TII->get(getOpcodeWithCC(MI.getOpcode(), NewCC))); + else + MI.getOperand(MI.getDesc().getNumOperands() - 1).setImm(NewCC); - // Insert a direct test of the saved register. - insertTest(MBB, CCMPI.getIterator(), CCMPI.getDebugLoc(), CondReg); - - // Rewrite the CCMP/CTEST to use the !ZF flag from the test, and then kill its - // use of the flags afterward. - CCMPI.getOperand(CCMPI.getDesc().getNumOperands() - 1) - .setImm(Inverted ? X86::COND_E : X86::COND_NE); - FlagUse.setIsKill(true); - LLVM_DEBUG(dbgs() << " fixed ccmp/ctest: "; CCMPI.dump()); + MI.findRegisterUseOperand(X86::EFLAGS, /*TRI=*/nullptr)->setIsKill(true); + LLVM_DEBUG(dbgs() << " fixed instruction: "; MI.dump()); } -- GitLab From 775d7ccc0fa1de4bb02e2f5cdf4ca38a021e873e Mon Sep 17 00:00:00 2001 From: Lukacma Date: Wed, 22 May 2024 10:50:22 +0100 Subject: [PATCH 091/452] [AArch64] Fix feature flags dependecies (#90612) This patch removes FEAT_FPMR from list of available of architecture features, instead enabling FMPR register by default. Additionally dependencies between architectural features are added and fixed. --- clang/test/Driver/aarch64-v95a.c | 8 +--- llvm/lib/Target/AArch64/AArch64Features.td | 46 +++++++++---------- llvm/lib/Target/AArch64/AArch64InstrInfo.td | 2 - .../Target/AArch64/AArch64SystemOperands.td | 2 - .../AArch64/AsmParser/AArch64AsmParser.cpp | 3 +- llvm/test/MC/AArch64/FP8/system-regs.s | 22 ++++----- .../TargetParser/TargetParserTest.cpp | 6 +-- 7 files changed, 35 insertions(+), 54 deletions(-) diff --git a/clang/test/Driver/aarch64-v95a.c b/clang/test/Driver/aarch64-v95a.c index 1037da65c8cb..62878f212762 100644 --- a/clang/test/Driver/aarch64-v95a.c +++ b/clang/test/Driver/aarch64-v95a.c @@ -6,7 +6,7 @@ // RUN: %clang -target aarch64 -mlittle-endian -march=armv9.5-a -### -c %s 2>&1 | FileCheck -check-prefix=GENERICV95A %s // RUN: %clang -target aarch64_be -mlittle-endian -march=armv9.5a -### -c %s 2>&1 | FileCheck -check-prefix=GENERICV95A %s // RUN: %clang -target aarch64_be -mlittle-endian -march=armv9.5-a -### -c %s 2>&1 | FileCheck -check-prefix=GENERICV95A %s -// GENERICV95A: "-cc1"{{.*}} "-triple" "aarch64{{.*}}" "-target-cpu" "generic" "-target-feature" "+v9.5a" +// GENERICV95A: "-cc1"{{.*}} "-triple" "aarch64{{.*}}" "-target-cpu" "generic" "-target-feature" "+v9.5a"{{.*}} "-target-feature" "+cpa"{{.*}} "-target-feature" "+faminmax"{{.*}} "-target-feature" "+lut" // RUN: %clang -target aarch64_be -march=armv9.5a -### -c %s 2>&1 | FileCheck -check-prefix=GENERICV95A-BE %s // RUN: %clang -target aarch64_be -march=armv9.5-a -### -c %s 2>&1 | FileCheck -check-prefix=GENERICV95A-BE %s @@ -14,14 +14,10 @@ // RUN: %clang -target aarch64 -mbig-endian -march=armv9.5-a -### -c %s 2>&1 | FileCheck -check-prefix=GENERICV95A-BE %s // RUN: %clang -target aarch64_be -mbig-endian -march=armv9.5a -### -c %s 2>&1 | FileCheck -check-prefix=GENERICV95A-BE %s // RUN: %clang -target aarch64_be -mbig-endian -march=armv9.5-a -### -c %s 2>&1 | FileCheck -check-prefix=GENERICV95A-BE %s -// GENERICV95A-BE: "-cc1"{{.*}} "-triple" "aarch64_be{{.*}}" "-target-cpu" "generic" "-target-feature" "+v9.5a" +// GENERICV95A-BE: "-cc1"{{.*}} "-triple" "aarch64_be{{.*}}" "-target-cpu" "generic" "-target-feature" "+v9.5a"{{.*}} "-target-feature" "+cpa"{{.*}} "-target-feature" "+faminmax"{{.*}} "-target-feature" "+lut" // ===== Features supported on aarch64 ===== -// RUN: %clang -target aarch64 -march=armv9.5a+cpa -### -c %s 2>&1 | FileCheck -check-prefix=V95A-CPA %s -// RUN: %clang -target aarch64 -march=armv9.5-a+cpa -### -c %s 2>&1 | FileCheck -check-prefix=V95A-CPA %s -// V95A-CPA: "-cc1"{{.*}} "-triple" "aarch64{{.*}}" "-target-cpu" "generic" "-target-feature" "+v9.5a"{{.*}} "-target-feature" "+cpa" - // RUN: %clang -target aarch64 -march=armv9.5a+pauth-lr -### -c %s 2>&1 | FileCheck -check-prefix=V95A-PAUTHLR %s // RUN: %clang -target aarch64 -march=armv9.5-a+pauth-lr -### -c %s 2>&1 | FileCheck -check-prefix=V95A-PAUTHLR %s // V95A-PAUTHLR: "-cc1"{{.*}} "-triple" "aarch64{{.*}}" "-target-cpu" "generic" "-target-feature" "+v9.5a"{{.*}} "-target-feature" "+pauth-lr" diff --git a/llvm/lib/Target/AArch64/AArch64Features.td b/llvm/lib/Target/AArch64/AArch64Features.td index ba0b760ce3d7..ffb899a30145 100644 --- a/llvm/lib/Target/AArch64/AArch64Features.td +++ b/llvm/lib/Target/AArch64/AArch64Features.td @@ -223,13 +223,6 @@ def FeatureSVE : Extension<"sve", "SVE", "Enable Scalable Vector Extension (SVE) instructions (FEAT_SVE)", [FeatureFullFP16], "FEAT_SVE", "+sve,+fullfp16,+fp-armv8,+neon", 310>; -def FeatureFPMR : Extension<"fpmr", "FPMR", - "Enable FPMR Register (FEAT_FPMR)">; - -let FMVDependencies = "+fpmr" in -def FeatureFP8 : Extension<"fp8", "FP8", - "Enable FP8 instructions (FEAT_FP8)">; - // This flag is currently still labeled as Experimental, but when fully // implemented this should tell the compiler to use the zeroing pseudos to // benefit from the reverse instructions (e.g. SUB vs SUBR) if the inactive @@ -667,41 +660,44 @@ def FeatureSME2p1 : Extension<"sme2p1", "SME2p1", def FeatureFAMINMAX: Extension<"faminmax", "FAMINMAX", "Enable FAMIN and FAMAX instructions (FEAT_FAMINMAX)">; -let FMVDependencies = "+fpmr" in +def FeatureLUT: Extension<"lut", "LUT", + "Enable Lookup Table instructions (FEAT_LUT)">; + +def FeatureFP8 : Extension<"fp8", "FP8", + "Enable FP8 instructions (FEAT_FP8)", [FeatureFAMINMAX, FeatureLUT, FeatureBF16]>; + def FeatureFP8FMA : Extension<"fp8fma", "FP8FMA", - "Enable fp8 multiply-add instructions (FEAT_FP8FMA)">; + "Enable fp8 multiply-add instructions (FEAT_FP8FMA)", [FeatureFP8]>; let FMVDependencies = "+sme2" in def FeatureSSVE_FP8FMA : Extension<"ssve-fp8fma", "SSVE_FP8FMA", - "Enable SVE2 fp8 multiply-add instructions (FEAT_SSVE_FP8FMA)", [FeatureSME2]>; + "Enable SVE2 fp8 multiply-add instructions (FEAT_SSVE_FP8FMA)", [FeatureSME2, FeatureFP8]>; +def FeatureFP8DOT4: Extension<"fp8dot4", "FP8DOT4", + "Enable fp8 4-way dot instructions (FEAT_FP8DOT4)", [FeatureFP8FMA]>; + def FeatureFP8DOT2: Extension<"fp8dot2", "FP8DOT2", - "Enable fp8 2-way dot instructions (FEAT_FP8DOT2)">; + "Enable fp8 2-way dot instructions (FEAT_FP8DOT2)", [FeatureFP8DOT4]>; let FMVDependencies = "+sme2" in -def FeatureSSVE_FP8DOT2 : Extension<"ssve-fp8dot2", "SSVE_FP8DOT2", - "Enable SVE2 fp8 2-way dot product instructions (FEAT_SSVE_FP8DOT2)", [FeatureSME2]>; - -def FeatureFP8DOT4: Extension<"fp8dot4", "FP8DOT4", - "Enable fp8 4-way dot instructions (FEAT_FP8DOT4)">; +def FeatureSSVE_FP8DOT4 : Extension<"ssve-fp8dot4", "SSVE_FP8DOT4", + "Enable SVE2 fp8 4-way dot product instructions (FEAT_SSVE_FP8DOT4)", [FeatureSSVE_FP8FMA]>; let FMVDependencies = "+sme2" in -def FeatureSSVE_FP8DOT4 : Extension<"ssve-fp8dot4", "SSVE_FP8DOT4", - "Enable SVE2 fp8 4-way dot product instructions (FEAT_SSVE_FP8DOT4)", [FeatureSME2]>; -def FeatureLUT: Extension<"lut", "LUT", - "Enable Lookup Table instructions (FEAT_LUT)">; +def FeatureSSVE_FP8DOT2 : Extension<"ssve-fp8dot2", "SSVE_FP8DOT2", + "Enable SVE2 fp8 2-way dot product instructions (FEAT_SSVE_FP8DOT2)", [FeatureSSVE_FP8DOT4]>; def FeatureSME_LUTv2 : Extension<"sme-lutv2", "SME_LUTv2", "Enable Scalable Matrix Extension (SME) LUTv2 instructions (FEAT_SME_LUTv2)">; -let FMVDependencies = "+fp8,+sme2" in -def FeatureSMEF8F16 : Extension<"sme-f8f16", "SMEF8F16", - "Enable Scalable Matrix Extension (SME) F8F16 instructions(FEAT_SME_F8F16)", [FeatureSME2, FeatureFP8]>; - let FMVDependencies = "+sme2,+fp8" in def FeatureSMEF8F32 : Extension<"sme-f8f32", "SMEF8F32", "Enable Scalable Matrix Extension (SME) F8F32 instructions (FEAT_SME_F8F32)", [FeatureSME2, FeatureFP8]>; +let FMVDependencies = "+fp8,+sme2" in +def FeatureSMEF8F16 : Extension<"sme-f8f16", "SMEF8F16", + "Enable Scalable Matrix Extension (SME) F8F16 instructions(FEAT_SME_F8F16)", [FeatureSMEF8F32]>; + def FeatureAppleA7SysReg : SubtargetFeature<"apple-a7-sysreg", "HasAppleA7SysReg", "true", "Apple A7 (the CPU formerly known as Cyclone)">; @@ -869,7 +865,7 @@ def HasV9_4aOps : Architecture64<9, 4, "a", "v9.4a", FeatureRASv2])>; def HasV9_5aOps : Architecture64<9, 5, "a", "v9.5a", [HasV9_4aOps, FeatureCPA], - !listconcat(HasV9_4aOps.DefaultExts, [FeatureCPA])>; + !listconcat(HasV9_4aOps.DefaultExts, [FeatureCPA, FeatureLUT, FeatureFAMINMAX])>; def HasV8_0rOps : Architecture64<8, 0, "r", "v8r", [ //v8.1 FeatureCRC, FeaturePAN, FeatureLSE, FeatureCONTEXTIDREL2, diff --git a/llvm/lib/Target/AArch64/AArch64InstrInfo.td b/llvm/lib/Target/AArch64/AArch64InstrInfo.td index a39e3b7be76d..4830033b2352 100644 --- a/llvm/lib/Target/AArch64/AArch64InstrInfo.td +++ b/llvm/lib/Target/AArch64/AArch64InstrInfo.td @@ -171,8 +171,6 @@ def HasSME2 : Predicate<"Subtarget->hasSME2()">, AssemblerPredicateWithAll<(all_of FeatureSME2), "sme2">; def HasSME2p1 : Predicate<"Subtarget->hasSME2p1()">, AssemblerPredicateWithAll<(all_of FeatureSME2p1), "sme2p1">; -def HasFPMR : Predicate<"Subtarget->hasFPMR()">, - AssemblerPredicateWithAll<(all_of FeatureFPMR), "fpmr">; def HasFP8 : Predicate<"Subtarget->hasFP8()">, AssemblerPredicateWithAll<(all_of FeatureFP8), "fp8">; def HasFAMINMAX : Predicate<"Subtarget->hasFAMINMAX()">, diff --git a/llvm/lib/Target/AArch64/AArch64SystemOperands.td b/llvm/lib/Target/AArch64/AArch64SystemOperands.td index 0564741c4970..0b5bc97674c7 100644 --- a/llvm/lib/Target/AArch64/AArch64SystemOperands.td +++ b/llvm/lib/Target/AArch64/AArch64SystemOperands.td @@ -1943,11 +1943,9 @@ def : RWSysReg<"PM", 0b11, 0b000, 0b0100, 0b0011, 0b001>; // 2023 ISA Extension // AArch64 Floating-point Mode Register controls behaviors of the FP8 // instructions (FEAT_FPMR) -let Requires = [{ {AArch64::FeatureFPMR} }] in { // Op0 Op1 CRn CRm Op2 def : ROSysReg<"ID_AA64FPFR0_EL1", 0b11, 0b000, 0b0000, 0b0100, 0b111>; def : RWSysReg<"FPMR", 0b11, 0b011, 0b0100, 0b0100, 0b010>; -} // v9.5a Software Stepping Enhancements (FEAT_STEP2) // Op0 Op1 CRn CRm Op2 diff --git a/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp b/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp index c9bba9bf6314..13a68b7dcf98 100644 --- a/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp +++ b/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp @@ -3718,7 +3718,6 @@ static const struct Extension { {"sb", {AArch64::FeatureSB}}, {"ssbs", {AArch64::FeatureSSBS}}, {"tme", {AArch64::FeatureTME}}, - {"fpmr", {AArch64::FeatureFPMR}}, {"fp8", {AArch64::FeatureFP8}}, {"faminmax", {AArch64::FeatureFAMINMAX}}, {"fp8fma", {AArch64::FeatureFP8FMA}}, @@ -3731,7 +3730,7 @@ static const struct Extension { {"sme-lutv2", {AArch64::FeatureSME_LUTv2}}, {"sme-f8f16", {AArch64::FeatureSMEF8F16}}, {"sme-f8f32", {AArch64::FeatureSMEF8F32}}, - {"sme-fa64", {AArch64::FeatureSMEFA64}}, + {"sme-fa64", {AArch64::FeatureSMEFA64}}, {"cpa", {AArch64::FeatureCPA}}, {"tlbiw", {AArch64::FeatureTLBIW}}, }; diff --git a/llvm/test/MC/AArch64/FP8/system-regs.s b/llvm/test/MC/AArch64/FP8/system-regs.s index 4a396d4dff82..8959a7727b19 100644 --- a/llvm/test/MC/AArch64/FP8/system-regs.s +++ b/llvm/test/MC/AArch64/FP8/system-regs.s @@ -1,11 +1,9 @@ -// RUN: llvm-mc -triple=aarch64 -show-encoding -mattr=+fpmr < %s \ +// RUN: llvm-mc -triple=aarch64 -show-encoding < %s \ // RUN: | FileCheck %s --check-prefixes=CHECK-ENCODING,CHECK-INST -// RUN: not llvm-mc -triple=aarch64 -show-encoding < %s 2>&1 \ -// RUN: | FileCheck %s --check-prefix=CHECK-ERROR -// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+fpmr < %s \ -// RUN: | llvm-objdump -d --mattr=+fpmr - | FileCheck %s --check-prefix=CHECK-INST -// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+fpmr < %s \ -// RUN: | llvm-objdump --mattr=-fpmr -d - | FileCheck %s --check-prefix=CHECK-UNKNOWN +// RUN: llvm-mc -triple=aarch64 -filetype=obj < %s \ +// RUN: | llvm-objdump -d - | FileCheck %s --check-prefix=CHECK-INST +// RUN: llvm-mc -triple=aarch64 -filetype=obj < %s \ +// RUN: | llvm-objdump -d - | FileCheck %s --check-prefix=CHECK-UNKNOWN // --------------------------------------------------------------------------// // read @@ -13,14 +11,13 @@ mrs x3, FPMR // CHECK-INST: mrs x3, FPMR // CHECK-ENCODING: [0x43,0x44,0x3b,0xd5] -// CHECK-ERROR: expected readable system register -// CHECK-UNKNOWN: d53b4443 mrs x3, S3_3_C4_C4_2 +// CHECK-UNKNOWN: d53b4443 mrs x3, FPMR + mrs x3, ID_AA64FPFR0_EL1 // CHECK-INST: mrs x3, ID_AA64FPFR0_EL1 // CHECK-ENCODING: [0xe3,0x04,0x38,0xd5] -// CHECK-ERROR: expected readable system register -// CHECK-UNKNOWN: d53804e3 mrs x3, S3_0_C0_C4_7 +// CHECK-UNKNOWN: d53804e3 mrs x3, ID_AA64FPFR0_EL1 // --------------------------------------------------------------------------// // write @@ -28,5 +25,4 @@ mrs x3, ID_AA64FPFR0_EL1 msr FPMR, x3 // CHECK-INST: msr FPMR, x3 // CHECK-ENCODING: [0x43,0x44,0x1b,0xd5] -// CHECK-ERROR: expected writable system register or pstate -// CHECK-UNKNOWN: d51b4443 msr S3_3_C4_C4_2, x3 +// CHECK-UNKNOWN: d51b4443 msr FPMR, x3 \ No newline at end of file diff --git a/llvm/unittests/TargetParser/TargetParserTest.cpp b/llvm/unittests/TargetParser/TargetParserTest.cpp index 0455e061f0bf..797d7dfbca20 100644 --- a/llvm/unittests/TargetParser/TargetParserTest.cpp +++ b/llvm/unittests/TargetParser/TargetParserTest.cpp @@ -1996,7 +1996,6 @@ TEST(TargetParserTest, AArch64ExtensionFeatures) { AArch64::AEK_D128, AArch64::AEK_LSE128, AArch64::AEK_SPECRES2, AArch64::AEK_RASV2, AArch64::AEK_ITE, AArch64::AEK_GCS, - AArch64::AEK_FPMR, AArch64::AEK_FP8, AArch64::AEK_FAMINMAX, AArch64::AEK_FP8FMA, AArch64::AEK_SSVE_FP8FMA, AArch64::AEK_FP8DOT2, AArch64::AEK_SSVE_FP8DOT2, AArch64::AEK_FP8DOT4, @@ -2005,7 +2004,8 @@ TEST(TargetParserTest, AArch64ExtensionFeatures) { AArch64::AEK_SMEF8F32, AArch64::AEK_SMEFA64, AArch64::AEK_CPA, AArch64::AEK_PAUTHLR, AArch64::AEK_TLBIW, AArch64::AEK_JSCVT, - AArch64::AEK_FCMA, + AArch64::AEK_FCMA, AArch64::AEK_FP8, + }; std::vector Features; @@ -2078,7 +2078,6 @@ TEST(TargetParserTest, AArch64ExtensionFeatures) { EXPECT_TRUE(llvm::is_contained(Features, "+specres2")); EXPECT_TRUE(llvm::is_contained(Features, "+ite")); EXPECT_TRUE(llvm::is_contained(Features, "+gcs")); - EXPECT_TRUE(llvm::is_contained(Features, "+fpmr")); EXPECT_TRUE(llvm::is_contained(Features, "+fp8")); EXPECT_TRUE(llvm::is_contained(Features, "+faminmax")); EXPECT_TRUE(llvm::is_contained(Features, "+fp8fma")); @@ -2224,7 +2223,6 @@ TEST(TargetParserTest, AArch64ArchExtFeature) { {"predres2", "nopredres2", "+specres2", "-specres2"}, {"rasv2", "norasv2", "+rasv2", "-rasv2"}, {"gcs", "nogcs", "+gcs", "-gcs"}, - {"fpmr", "nofpmr", "+fpmr", "-fpmr"}, {"fp8", "nofp8", "+fp8", "-fp8"}, {"faminmax", "nofaminmax", "+faminmax", "-faminmax"}, {"fp8fma", "nofp8fma", "+fp8fma", "-fp8fma"}, -- GitLab From 1f5cd3accd7e98abbf31d45b1ed59fbda0c91d30 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timm=20B=C3=A4der?= Date: Tue, 21 May 2024 09:46:19 +0200 Subject: [PATCH 092/452] [clang][Interp][NFC] Fix getType() of pointers pointing to vector elems --- clang/lib/AST/Interp/Pointer.h | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/clang/lib/AST/Interp/Pointer.h b/clang/lib/AST/Interp/Pointer.h index 3ade5756e580..9468bdbf00cc 100644 --- a/clang/lib/AST/Interp/Pointer.h +++ b/clang/lib/AST/Interp/Pointer.h @@ -314,12 +314,14 @@ public: /// Returns the type of the innermost field. QualType getType() const { if (inPrimitiveArray() && Offset != asBlockPointer().Base) { - // Unfortunately, complex types are not array types in clang, but they are - // for us. + // Unfortunately, complex and vector types are not array types in clang, + // but they are for us. if (const auto *AT = getFieldDesc()->getType()->getAsArrayTypeUnsafe()) return AT->getElementType(); if (const auto *CT = getFieldDesc()->getType()->getAs()) return CT->getElementType(); + if (const auto *CT = getFieldDesc()->getType()->getAs()) + return CT->getElementType(); } return getFieldDesc()->getType(); } -- GitLab From f156b9ce7aae520046c926458ed17d73ed33fc2a Mon Sep 17 00:00:00 2001 From: Abid Qadeer Date: Wed, 22 May 2024 10:59:29 +0100 Subject: [PATCH 093/452] [flang] Add debug information for module variables. (#91582) This PR add debug info for module variables. The module variables are added as global variables but their scope is set to module instead of compile unit. The scope of function declared inside a module is also set accordingly. After this patch, a module variable could be evaluated in the GDB as `p helper::gli` where helper is name of the module and gli is the name of the variable. A future patch will add the import module functionality which will remove the need to prefix the name with helper::. The line number where is module is declared is a best guess at the moment as this information is not part of the GlobalOp. --- flang/lib/Optimizer/CodeGen/CodeGen.cpp | 17 +++- .../lib/Optimizer/Transforms/AddDebugInfo.cpp | 89 ++++++++++++++++++- flang/test/Integration/debug-module-2.f90 | 39 ++++++++ flang/test/Transforms/debug-module-1.fir | 40 +++++++++ flang/test/Transforms/debug-module-2.fir | 35 ++++++++ 5 files changed, 217 insertions(+), 3 deletions(-) create mode 100644 flang/test/Integration/debug-module-2.f90 create mode 100644 flang/test/Transforms/debug-module-1.fir create mode 100644 flang/test/Transforms/debug-module-2.fir diff --git a/flang/lib/Optimizer/CodeGen/CodeGen.cpp b/flang/lib/Optimizer/CodeGen/CodeGen.cpp index 72172f63888e..fb7afcf07713 100644 --- a/flang/lib/Optimizer/CodeGen/CodeGen.cpp +++ b/flang/lib/Optimizer/CodeGen/CodeGen.cpp @@ -2716,6 +2716,18 @@ struct GlobalOpConversion : public fir::FIROpConversion { mlir::LogicalResult matchAndRewrite(fir::GlobalOp global, OpAdaptor adaptor, mlir::ConversionPatternRewriter &rewriter) const override { + + mlir::LLVM::DIGlobalVariableExpressionAttr dbgExpr; + + if (auto fusedLoc = mlir::dyn_cast(global.getLoc())) { + if (auto gvAttr = + mlir::dyn_cast_or_null( + fusedLoc.getMetadata())) { + dbgExpr = mlir::LLVM::DIGlobalVariableExpressionAttr::get( + global.getContext(), gvAttr, mlir::LLVM::DIExpressionAttr()); + } + } + auto tyAttr = convertType(global.getType()); if (auto boxType = mlir::dyn_cast(global.getType())) tyAttr = this->lowerTy().convertBoxTypeAsStruct(boxType); @@ -2724,8 +2736,11 @@ struct GlobalOpConversion : public fir::FIROpConversion { assert(attributeTypeIsCompatible(global.getContext(), initAttr, tyAttr)); auto linkage = convertLinkage(global.getLinkName()); auto isConst = global.getConstant().has_value(); + mlir::SymbolRefAttr comdat; + llvm::ArrayRef attrs; auto g = rewriter.create( - loc, tyAttr, isConst, linkage, global.getSymName(), initAttr); + loc, tyAttr, isConst, linkage, global.getSymName(), initAttr, 0, 0, + false, false, comdat, attrs, dbgExpr); auto module = global->getParentOfType(); // Add comdat if necessary diff --git a/flang/lib/Optimizer/Transforms/AddDebugInfo.cpp b/flang/lib/Optimizer/Transforms/AddDebugInfo.cpp index 07e8aed4cd07..fb7c0bf0d1f9 100644 --- a/flang/lib/Optimizer/Transforms/AddDebugInfo.cpp +++ b/flang/lib/Optimizer/Transforms/AddDebugInfo.cpp @@ -54,6 +54,16 @@ class AddDebugInfoPass : public fir::impl::AddDebugInfoBase { public: AddDebugInfoPass(fir::AddDebugInfoOptions options) : Base(options) {} void runOnOperation() override; + +private: + llvm::StringMap moduleMap; + + mlir::LLVM::DIModuleAttr getOrCreateModuleAttr( + const std::string &name, mlir::LLVM::DIFileAttr fileAttr, + mlir::LLVM::DIScopeAttr scope, unsigned line, bool decl); + + void handleGlobalOp(fir::GlobalOp glocalOp, mlir::LLVM::DIFileAttr fileAttr, + mlir::LLVM::DIScopeAttr scope); }; static uint32_t getLineFromLoc(mlir::Location loc) { @@ -99,6 +109,70 @@ void AddDebugInfoPass::handleDeclareOp(fir::cg::XDeclareOp declOp, declOp->setLoc(builder.getFusedLoc({declOp->getLoc()}, localVarAttr)); } +// The `module` does not have a first class representation in the `FIR`. We +// extract information about it from the name of the identifiers and keep a +// map to avoid duplication. +mlir::LLVM::DIModuleAttr AddDebugInfoPass::getOrCreateModuleAttr( + const std::string &name, mlir::LLVM::DIFileAttr fileAttr, + mlir::LLVM::DIScopeAttr scope, unsigned line, bool decl) { + mlir::MLIRContext *context = &getContext(); + mlir::LLVM::DIModuleAttr modAttr; + if (auto iter{moduleMap.find(name)}; iter != moduleMap.end()) { + modAttr = iter->getValue(); + } else { + modAttr = mlir::LLVM::DIModuleAttr::get( + context, fileAttr, scope, mlir::StringAttr::get(context, name), + /* configMacros */ mlir::StringAttr(), + /* includePath */ mlir::StringAttr(), + /* apinotes */ mlir::StringAttr(), line, decl); + moduleMap[name] = modAttr; + } + return modAttr; +} + +void AddDebugInfoPass::handleGlobalOp(fir::GlobalOp globalOp, + mlir::LLVM::DIFileAttr fileAttr, + mlir::LLVM::DIScopeAttr scope) { + mlir::ModuleOp module = getOperation(); + mlir::MLIRContext *context = &getContext(); + fir::DebugTypeGenerator typeGen(module); + mlir::OpBuilder builder(context); + + std::pair result = fir::NameUniquer::deconstruct(globalOp.getSymName()); + if (result.first != fir::NameUniquer::NameKind::VARIABLE) + return; + + unsigned line = getLineFromLoc(globalOp.getLoc()); + + // DWARF5 says following about the fortran modules: + // A Fortran 90 module may also be represented by a module entry + // (but no declaration attribute is warranted because Fortran has no concept + // of a corresponding module body). + // But in practice, compilers use declaration attribute with a module in cases + // where module was defined in another source file (only being used in this + // one). The isInitialized() seems to provide the right information + // but inverted. It is true where module is actually defined but false where + // it is used. + // FIXME: Currently we don't have the line number on which a module was + // declared. We are using a best guess of line - 1 where line is the source + // line of the first member of the module that we encounter. + + if (result.second.modules.empty()) + return; + + scope = getOrCreateModuleAttr(result.second.modules[0], fileAttr, scope, + line - 1, !globalOp.isInitialized()); + + mlir::LLVM::DITypeAttr diType = typeGen.convertType( + globalOp.getType(), fileAttr, scope, globalOp.getLoc()); + auto gvAttr = mlir::LLVM::DIGlobalVariableAttr::get( + context, scope, mlir::StringAttr::get(context, result.second.name), + mlir::StringAttr::get(context, globalOp.getName()), fileAttr, line, + diType, /*isLocalToUnit*/ false, + /*isDefinition*/ globalOp.isInitialized(), /* alignInBits*/ 0); + globalOp->setLoc(builder.getFusedLoc({globalOp->getLoc()}, gvAttr)); +} + void AddDebugInfoPass::runOnOperation() { mlir::ModuleOp module = getOperation(); mlir::MLIRContext *context = &getContext(); @@ -138,6 +212,12 @@ void AddDebugInfoPass::runOnOperation() { llvm::dwarf::getLanguage("DW_LANG_Fortran95"), fileAttr, producer, isOptimized, debugLevel); + if (debugLevel == mlir::LLVM::DIEmissionKind::Full) { + // Process 'GlobalOp' only if full debug info is requested. + for (auto globalOp : module.getOps()) + handleGlobalOp(globalOp, fileAttr, cuAttr); + } + module.walk([&](mlir::func::FuncOp funcOp) { mlir::Location l = funcOp->getLoc(); // If fused location has already been created then nothing to do @@ -180,6 +260,7 @@ void AddDebugInfoPass::runOnOperation() { // Only definitions need a distinct identifier and a compilation unit. mlir::DistinctAttr id; + mlir::LLVM::DIScopeAttr Scope = fileAttr; mlir::LLVM::DICompileUnitAttr compilationUnit; mlir::LLVM::DISubprogramFlags subprogramFlags = mlir::LLVM::DISubprogramFlags{}; @@ -192,9 +273,13 @@ void AddDebugInfoPass::runOnOperation() { subprogramFlags | mlir::LLVM::DISubprogramFlags::Definition; } unsigned line = getLineFromLoc(l); + if (!result.second.modules.empty()) + Scope = getOrCreateModuleAttr(result.second.modules[0], fileAttr, cuAttr, + line - 1, false); + auto spAttr = mlir::LLVM::DISubprogramAttr::get( - context, id, compilationUnit, fileAttr, funcName, fullName, - funcFileAttr, line, line, subprogramFlags, subTypeAttr); + context, id, compilationUnit, Scope, funcName, fullName, funcFileAttr, + line, line, subprogramFlags, subTypeAttr); funcOp->setLoc(builder.getFusedLoc({funcOp->getLoc()}, spAttr)); // Don't process variables if user asked for line tables only. diff --git a/flang/test/Integration/debug-module-2.f90 b/flang/test/Integration/debug-module-2.f90 new file mode 100644 index 000000000000..60fccaa2a6c1 --- /dev/null +++ b/flang/test/Integration/debug-module-2.f90 @@ -0,0 +1,39 @@ +! RUN: %flang_fc1 -emit-llvm -debug-info-kind=standalone %s -o - | FileCheck %s +! RUN: %flang_fc1 -emit-llvm -debug-info-kind=line-tables-only %s -o - | FileCheck --check-prefix=LINEONLY %s + +! CHECK-DAG: ![[FILE:.*]] = !DIFile(filename: {{.*}}debug-module-2.f90{{.*}}) +! CHECK-DAG: ![[FILE2:.*]] = !DIFile(filename: {{.*}}debug-module-2.f90{{.*}}) +! CHECK-DAG: ![[CU:.*]] = distinct !DICompileUnit({{.*}}file: ![[FILE]]{{.*}} globals: ![[GLOBALS:.*]]) +! CHECK-DAG: ![[MOD:.*]] = !DIModule(scope: ![[CU]], name: "helper", file: ![[FILE]]{{.*}}) +! CHECK-DAG: ![[R4:.*]] = !DIBasicType(name: "real", size: 32, encoding: DW_ATE_float) +! CHECK-DAG: ![[I4:.*]] = !DIBasicType(name: "integer", size: 32, encoding: DW_ATE_signed) +module helper +! CHECK-DAG: ![[GLR:.*]] = distinct !DIGlobalVariable(name: "glr", linkageName: "_QMhelperEglr", scope: ![[MOD]], file: ![[FILE]], line: [[@LINE+2]], type: ![[R4]], isLocal: false, isDefinition: true) +! CHECK-DAG: ![[GLRX:.*]] = !DIGlobalVariableExpression(var: ![[GLR]], expr: !DIExpression()) + real glr + +! CHECK-DAG: ![[GLI:.*]] = distinct !DIGlobalVariable(name: "gli", linkageName: "_QMhelperEgli", scope: ![[MOD]], file: ![[FILE]], line: [[@LINE+2]], type: ![[I4]], isLocal: false, isDefinition: true) +! CHECK-DAG: ![[GLIX:.*]] = !DIGlobalVariableExpression(var: ![[GLI]], expr: !DIExpression()) + integer gli + + contains +!CHECK-DAG: !DISubprogram(name: "test", linkageName: "_QMhelperPtest", scope: ![[MOD]], file: ![[FILE2]], line: [[@LINE+1]]{{.*}}unit: ![[CU]]) + subroutine test() + glr = 12.34 + gli = 67 + + end subroutine +end module helper + +program test +use helper +implicit none + + glr = 3.14 + gli = 2 + call test() + +end program test + +! CHECK-DAG: ![[GLOBALS]] = !{![[GLIX]], ![[GLRX]]} +! LINEONLY-NOT: DIGlobalVariable diff --git a/flang/test/Transforms/debug-module-1.fir b/flang/test/Transforms/debug-module-1.fir new file mode 100644 index 000000000000..822ae01b99aa --- /dev/null +++ b/flang/test/Transforms/debug-module-1.fir @@ -0,0 +1,40 @@ +// RUN: fir-opt --add-debug-info --mlir-print-debuginfo %s | FileCheck %s + + +module attributes {} { + fir.global @_QMhelperEgli : i32 { + %0 = fir.zero_bits i32 + fir.has_value %0 : i32 + } loc(#loc1) + fir.global @_QMhelperEglr : f32 { + %0 = fir.zero_bits f32 + fir.has_value %0 : f32 + } loc(#loc2) + func.func @_QMhelperPtest() { + %c67_i32 = arith.constant 67 : i32 + %cst = arith.constant 1.234000e+01 : f32 + %0 = fir.address_of(@_QMhelperEgli) : !fir.ref + %1 = fir.address_of(@_QMhelperEglr) : !fir.ref + fir.store %cst to %1 : !fir.ref + fir.store %c67_i32 to %0 : !fir.ref + return + } loc(#loc3) +} +#loc1 = loc("test.f90":12:11) +#loc2 = loc("test.f90":15:8) +#loc3 = loc("test.f90":20:5) + +// CHECK-DAG: #[[I4:.*]] = #llvm.di_basic_type +// CHECK-DAG: #[[R4:.*]] = #llvm.di_basic_type +// CHECK-DAG: #[[CU:.*]] = #llvm.di_compile_unit<{{.*}}> +// CHECK-DAG: #[[MOD:.*]] = #llvm.di_module<{{.*}}scope = #[[CU]], name = "helper"{{.*}}> +// CHECK-DAG: #[[LOC1:.*]] = loc("{{.*}}test.f90":12{{.*}}) +// CHECK-DAG: #[[GLI:.*]] = #llvm.di_global_variable +// CHECK-DAG: #[[LOC2:.*]] = loc("{{.*}}test.f90":15{{.*}}) +// CHECK-DAG: #[[GLR:.*]] = #llvm.di_global_variable +// CHECK-DAG: #[[LOC3:.*]] = loc("{{.*}}test.f90":20{{.*}}) +// CHECK-DAG: #[[TEST:.*]] = #llvm.di_subprogram<{{.*}}compileUnit = #[[CU]], scope = #[[MOD]], name = "test", linkageName = "_QMhelperPtest"{{.*}}line = 20, scopeLine = 20{{.*}}> +// CHECK-DAG: loc(fused<#[[GLI]]>[#[[LOC1]]]) +// CHECK-DAG: loc(fused<#[[GLR]]>[#[[LOC2]]]) +// CHECK-DAG: loc(fused<#[[TEST]]>[#[[LOC3]]]) + diff --git a/flang/test/Transforms/debug-module-2.fir b/flang/test/Transforms/debug-module-2.fir new file mode 100644 index 000000000000..6acdc1df23d2 --- /dev/null +++ b/flang/test/Transforms/debug-module-2.fir @@ -0,0 +1,35 @@ +// RUN: fir-opt --fir-to-llvm-ir="target=x86_64-unknown-linux-gnu" --mlir-print-debuginfo %s | FileCheck %s + +module { + fir.global @_QMhelperEgli : i32 { + %0 = fir.zero_bits i32 + fir.has_value %0 : i32 + } loc(#loc3) + fir.global @_QMhelperEglr : f32 { + %0 = fir.zero_bits f32 + fir.has_value %0 : f32 + } loc(#loc4) +} +#di_basic_type = #llvm.di_basic_type +#di_basic_type1 = #llvm.di_basic_type + +#di_file = #llvm.di_file<"test.f90" in ""> +#di_subroutine_type = #llvm.di_subroutine_type + +#di_compile_unit = #llvm.di_compile_unit, sourceLanguage = DW_LANG_Fortran95, file = #di_file, producer = "flang version 19.0.0 (/home/haqadeer/work/llvm-project/flang 5d5c73cad421bdca6e43e1cc10704ff160f1a33e)", isOptimized = false, emissionKind = Full> +#di_module = #llvm.di_module +#di_global_variable = #llvm.di_global_variable +#di_global_variable1 = #llvm.di_global_variable + +#loc1 = loc("test.f90":12:11) +#loc2 = loc("test.f90":15:8) +#loc3 = loc(fused<#di_global_variable>[#loc1]) +#loc4 = loc(fused<#di_global_variable1>[#loc2]) + + +// CHECK-DAG: #[[GLI:.*]] = #llvm.di_global_variable<{{.*}}name = "gli", linkageName = "_QMhelperEgli"{{.*}}> +// CHECK-DAG: #[[GLR:.*]] = #llvm.di_global_variable<{{.*}}name = "glr", linkageName = "_QMhelperEglr"{{.*}}> +// CHECK-DAG: #[[GLIE:.*]] = #llvm.di_global_variable_expression +// CHECK-DAG: #[[GLRE:.*]] = #llvm.di_global_variable_expression +// CHECK-DAG: llvm.mlir.global{{.*}}@_QMhelperEgli() {{{.*}}dbg_expr = #[[GLIE]]} +// CHECK-DAG: llvm.mlir.global{{.*}}@_QMhelperEglr() {{{.*}}dbg_expr = #[[GLRE]]} -- GitLab From 1b066437085b7906a70539aad170e3e52fb9f685 Mon Sep 17 00:00:00 2001 From: Simon Pilgrim Date: Wed, 22 May 2024 10:52:29 +0100 Subject: [PATCH 094/452] [X86] stack-folding-fp-avx512fp16.ll - remove broken CHECK-LABEl prefix lines Typo identified in #91854 --- llvm/test/CodeGen/X86/stack-folding-fp-avx512fp16.ll | 1 - 1 file changed, 1 deletion(-) diff --git a/llvm/test/CodeGen/X86/stack-folding-fp-avx512fp16.ll b/llvm/test/CodeGen/X86/stack-folding-fp-avx512fp16.ll index e4eca6b744af..ed7109c416e7 100644 --- a/llvm/test/CodeGen/X86/stack-folding-fp-avx512fp16.ll +++ b/llvm/test/CodeGen/X86/stack-folding-fp-avx512fp16.ll @@ -265,7 +265,6 @@ define i32 @stack_fold_fpclassph_mask(<32 x half> %a0, ptr %p) { } define i8 @stack_fold_fpclasssh(<8 x half> %a0) { - ;CHECK-LABEl: stack_fold_fpclasssh: ; CHECK-LABEL: stack_fold_fpclasssh: ; CHECK: # %bb.0: ; CHECK-NEXT: vmovaps %xmm0, {{[-0-9]+}}(%r{{[sb]}}p) # 16-byte Spill -- GitLab From 6381cfe8910bfd8cefb91b565b7640529e2f75f2 Mon Sep 17 00:00:00 2001 From: Simon Pilgrim Date: Wed, 22 May 2024 10:53:37 +0100 Subject: [PATCH 095/452] [X86] stack-frame-layout-remarks.ll - fix BOTH-Next -> BOTH-NEXT typo Typo identified in #91854 --- llvm/test/CodeGen/X86/stack-frame-layout-remarks.ll | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/llvm/test/CodeGen/X86/stack-frame-layout-remarks.ll b/llvm/test/CodeGen/X86/stack-frame-layout-remarks.ll index d32a37efcb5a..cd5edcf2ae50 100644 --- a/llvm/test/CodeGen/X86/stack-frame-layout-remarks.ll +++ b/llvm/test/CodeGen/X86/stack-frame-layout-remarks.ll @@ -35,7 +35,7 @@ entry: declare void @llvm.dbg.declare(metadata, metadata, metadata) #0 ; BOTH: Function: cleanup_array -; BOTH-Next: Offset: [SP+4], Type: Protector, Align: 16, Size: 4 +; BOTH-NEXT: Offset: [SP+4], Type: Protector, Align: 16, Size: 4 ; DEBUG: a @ dot.c:13 ; STRIPPED-NOT: a @ dot.c:13 ; BOTH: Offset: [SP-4], Type: Spill, Align: 8, Size: 4 -- GitLab From 0873b4ca295234d697172e32fa4e597ebbb63ee0 Mon Sep 17 00:00:00 2001 From: Simon Pilgrim Date: Wed, 22 May 2024 11:06:44 +0100 Subject: [PATCH 096/452] [LoopVectorize] optimal-epilog-vectorization-profitability.ll - fix LABLE -> LABEL typo Typo identified in #91854 --- .../PowerPC/optimal-epilog-vectorization-profitability.ll | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/llvm/test/Transforms/LoopVectorize/PowerPC/optimal-epilog-vectorization-profitability.ll b/llvm/test/Transforms/LoopVectorize/PowerPC/optimal-epilog-vectorization-profitability.ll index b88254e7b678..786197bfdb90 100644 --- a/llvm/test/Transforms/LoopVectorize/PowerPC/optimal-epilog-vectorization-profitability.ll +++ b/llvm/test/Transforms/LoopVectorize/PowerPC/optimal-epilog-vectorization-profitability.ll @@ -10,7 +10,7 @@ target datalayout = "e-m:e-i64:64-n32:64" target triple = "powerpc64le-unknown-linux-gnu" ; Do not vectorize epilogues for loops with minsize attribute -; CHECK-LABLE: @f1 +; CHECK-LABEL: @f1 ; CHECK-NOT: vector.main.loop.iter.check ; CHECK-NOT: vec.epilog.iter.check ; CHECK-NOT: vec.epilog.ph @@ -48,7 +48,7 @@ for.end: ; preds = %for.end.loopexit, % } ; Do not vectorize epilogues for loops with optsize attribute -; CHECK-LABLE: @f2 +; CHECK-LABEL: @f2 ; CHECK-NOT: vector.main.loop.iter.check ; CHECK-NOT: vec.epilog.iter.check ; CHECK-NOT: vec.epilog.ph @@ -86,7 +86,7 @@ for.end: ; preds = %for.end.loopexit, % } ; Do not vectorize the epilogue for loops with VF less than the default -epilogue-vectorization-minimum-VF of 16. -; CHECK-MIN-D-LABLE: @f3 +; CHECK-MIN-D-LABEL: @f3 ; CHECK-MIN-D-NOT: vector.main.loop.iter.check ; CHECK-MIN-D-NOT: vec.epilog.iter.check ; CHECK-MIN-D-NOT: vec.epilog.ph @@ -96,7 +96,7 @@ for.end: ; preds = %for.end.loopexit, % ; Specify a smaller minimum VF (via `-epilogue-vectorization-minimum-VF=4`) and ; make sure the epilogue gets vectorized in that case. -; CHECK-MIN-D-LABLE: @f3 +; CHECK-MIN-4-LABEL: @f3 ; CHECK-MIN-4: vector.main.loop.iter.check ; CHECK-MIN-4: vec.epilog.iter.check ; CHECK-MIN-4: vec.epilog.ph -- GitLab From 5d833c65da74d83a9b5df19da52d67ea1c0ecc10 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timm=20B=C3=A4der?= Date: Tue, 21 May 2024 11:12:01 +0200 Subject: [PATCH 097/452] [clang][Interp][NFC] Remove unneeded CheckRange call This doesn't do anything with the current tests and is unnecessary in general. --- clang/lib/AST/Interp/Interp.h | 3 --- 1 file changed, 3 deletions(-) diff --git a/clang/lib/AST/Interp/Interp.h b/clang/lib/AST/Interp/Interp.h index bc2ca126ce36..c5607169b25f 100644 --- a/clang/lib/AST/Interp/Interp.h +++ b/clang/lib/AST/Interp/Interp.h @@ -1538,9 +1538,6 @@ inline bool Memcpy(InterpState &S, CodePtr OpPC) { template bool OffsetHelper(InterpState &S, CodePtr OpPC, const T &Offset, const Pointer &Ptr) { - if (!CheckRange(S, OpPC, Ptr, CSK_ArrayToPointer)) - return false; - // A zero offset does not change the pointer. if (Offset.isZero()) { S.Stk.push(Ptr); -- GitLab From 11b97da83141db857361ec9535dcd637ffcd0439 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bal=C3=A1zs=20K=C3=A9ri?= Date: Wed, 22 May 2024 12:11:18 +0200 Subject: [PATCH 098/452] [clang][analyzer] Add checker 'security.SetgidSetuidOrder' (#91445) --- clang/docs/analyzer/checkers.rst | 41 +++ .../clang/StaticAnalyzer/Checkers/Checkers.td | 5 + .../StaticAnalyzer/Checkers/CMakeLists.txt | 1 + .../Checkers/SetgidSetuidOrderChecker.cpp | 196 +++++++++++++ .../test/Analysis/setgid-setuid-order-notes.c | 73 +++++ clang/test/Analysis/setgid-setuid-order.c | 257 ++++++++++++++++++ 6 files changed, 573 insertions(+) create mode 100644 clang/lib/StaticAnalyzer/Checkers/SetgidSetuidOrderChecker.cpp create mode 100644 clang/test/Analysis/setgid-setuid-order-notes.c create mode 100644 clang/test/Analysis/setgid-setuid-order.c diff --git a/clang/docs/analyzer/checkers.rst b/clang/docs/analyzer/checkers.rst index eb8b58323da4..b4bd9dac1cbc 100644 --- a/clang/docs/analyzer/checkers.rst +++ b/clang/docs/analyzer/checkers.rst @@ -1179,6 +1179,47 @@ security.insecureAPI.DeprecatedOrUnsafeBufferHandling (C) strncpy(buf, "a", 1); // warn } +security.SetgidSetuidOrder (C) +"""""""""""""""""""""""""""""" +When dropping user-level and group-level privileges in a program by using +``setuid`` and ``setgid`` calls, it is important to reset the group-level +privileges (with ``setgid``) first. Function ``setgid`` will likely fail if +the superuser privileges are already dropped. + +The checker checks for sequences of ``setuid(getuid())`` and +``setgid(getgid())`` calls (in this order). If such a sequence is found and +there is no other privilege-changing function call (``seteuid``, ``setreuid``, +``setresuid`` and the GID versions of these) in between, a warning is +generated. The checker finds only exactly ``setuid(getuid())`` calls (and the +GID versions), not for example if the result of ``getuid()`` is stored in a +variable. + +.. code-block:: c + + void test1() { + // ... + // end of section with elevated privileges + // reset privileges (user and group) to normal user + if (setuid(getuid()) != 0) { + handle_error(); + return; + } + if (setgid(getgid()) != 0) { // warning: A 'setgid(getgid())' call following a 'setuid(getuid())' call is likely to fail + handle_error(); + return; + } + // user-ID and group-ID are reset to normal user now + // ... + } + +In the code above the problem is that ``setuid(getuid())`` removes superuser +privileges before ``setgid(getgid())`` is called. To fix the problem the +``setgid(getgid())`` should be called first. Further attention is needed to +avoid code like ``setgid(getuid())`` (this checker does not detect bugs like +this) and always check the return value of these calls. + +This check corresponds to SEI CERT Rule `POS36-C `_. + .. _unix-checkers: unix diff --git a/clang/include/clang/StaticAnalyzer/Checkers/Checkers.td b/clang/include/clang/StaticAnalyzer/Checkers/Checkers.td index 64414e3d37f7..d0ba1ce54840 100644 --- a/clang/include/clang/StaticAnalyzer/Checkers/Checkers.td +++ b/clang/include/clang/StaticAnalyzer/Checkers/Checkers.td @@ -1011,6 +1011,11 @@ def FloatLoopCounter : Checker<"FloatLoopCounter">, Dependencies<[SecuritySyntaxChecker]>, Documentation; +def SetgidSetuidOrderChecker : Checker<"SetgidSetuidOrder">, + HelpText<"Warn on possible reversed order of 'setgid(getgid()))' and " + "'setuid(getuid())' (CERT: POS36-C)">, + Documentation; + } // end "security" let ParentPackage = ENV in { diff --git a/clang/lib/StaticAnalyzer/Checkers/CMakeLists.txt b/clang/lib/StaticAnalyzer/Checkers/CMakeLists.txt index 4443ffd09293..45d3788f105d 100644 --- a/clang/lib/StaticAnalyzer/Checkers/CMakeLists.txt +++ b/clang/lib/StaticAnalyzer/Checkers/CMakeLists.txt @@ -103,6 +103,7 @@ add_clang_library(clangStaticAnalyzerCheckers ReturnUndefChecker.cpp ReturnValueChecker.cpp RunLoopAutoreleaseLeakChecker.cpp + SetgidSetuidOrderChecker.cpp SimpleStreamChecker.cpp SmartPtrChecker.cpp SmartPtrModeling.cpp diff --git a/clang/lib/StaticAnalyzer/Checkers/SetgidSetuidOrderChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/SetgidSetuidOrderChecker.cpp new file mode 100644 index 000000000000..dbe3fd33a6b4 --- /dev/null +++ b/clang/lib/StaticAnalyzer/Checkers/SetgidSetuidOrderChecker.cpp @@ -0,0 +1,196 @@ +//===-- SetgidSetuidOrderChecker.cpp - check privilege revocation calls ---===// +// +// 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 +// +//===----------------------------------------------------------------------===// +// +// This file defines a checker to detect possible reversed order of privilege +// revocations when 'setgid' and 'setuid' is used. +// +//===----------------------------------------------------------------------===// + +#include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h" +#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h" +#include "clang/StaticAnalyzer/Core/Checker.h" +#include "clang/StaticAnalyzer/Core/CheckerManager.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/CallDescription.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h" + +using namespace clang; +using namespace ento; + +namespace { + +enum SetPrivilegeFunctionKind { Irrelevant, Setuid, Setgid }; + +class SetgidSetuidOrderChecker : public Checker { + const BugType BT{this, "Possible wrong order of privilege revocation"}; + + const CallDescription SetuidDesc{CDM::CLibrary, {"setuid"}, 1}; + const CallDescription SetgidDesc{CDM::CLibrary, {"setgid"}, 1}; + + const CallDescription GetuidDesc{CDM::CLibrary, {"getuid"}, 0}; + const CallDescription GetgidDesc{CDM::CLibrary, {"getgid"}, 0}; + + const CallDescriptionSet OtherSetPrivilegeDesc{ + {CDM::CLibrary, {"seteuid"}, 1}, {CDM::CLibrary, {"setegid"}, 1}, + {CDM::CLibrary, {"setreuid"}, 2}, {CDM::CLibrary, {"setregid"}, 2}, + {CDM::CLibrary, {"setresuid"}, 3}, {CDM::CLibrary, {"setresgid"}, 3}}; + +public: + void checkPostCall(const CallEvent &Call, CheckerContext &C) const; + ProgramStateRef evalAssume(ProgramStateRef State, SVal Cond, + bool Assumption) const; + +private: + void processSetuid(ProgramStateRef State, const CallEvent &Call, + CheckerContext &C) const; + void processSetgid(ProgramStateRef State, const CallEvent &Call, + CheckerContext &C) const; + void processOther(ProgramStateRef State, const CallEvent &Call, + CheckerContext &C) const; + /// Check if a function like \c getuid or \c getgid is called directly from + /// the first argument of function called from \a Call. + bool isFunctionCalledInArg(const CallDescription &Desc, + const CallEvent &Call) const; + void emitReport(ProgramStateRef State, CheckerContext &C) const; +}; + +} // end anonymous namespace + +/// Store if there was a call to 'setuid(getuid())' or 'setgid(getgid())' not +/// followed by other different privilege-change functions. +/// If the value \c Setuid is stored and a 'setgid(getgid())' call is found we +/// have found the bug to be reported. Value \c Setgid is used too to prevent +/// warnings at a setgid-setuid-setgid sequence. +REGISTER_TRAIT_WITH_PROGRAMSTATE(LastSetPrivilegeCall, SetPrivilegeFunctionKind) +/// Store the symbol value of the last 'setuid(getuid())' call. This is used to +/// detect if the result is compared to -1 and avoid warnings on that branch +/// (which is the failure branch of the call), and for identification of note +/// tags. +REGISTER_TRAIT_WITH_PROGRAMSTATE(LastSetuidCallSVal, SymbolRef) + +void SetgidSetuidOrderChecker::checkPostCall(const CallEvent &Call, + CheckerContext &C) const { + ProgramStateRef State = C.getState(); + if (SetuidDesc.matches(Call)) { + processSetuid(State, Call, C); + } else if (SetgidDesc.matches(Call)) { + processSetgid(State, Call, C); + } else if (OtherSetPrivilegeDesc.contains(Call)) { + processOther(State, Call, C); + } +} + +ProgramStateRef SetgidSetuidOrderChecker::evalAssume(ProgramStateRef State, + SVal Cond, + bool Assumption) const { + SValBuilder &SVB = State->getStateManager().getSValBuilder(); + SymbolRef LastSetuidSym = State->get(); + if (!LastSetuidSym) + return State; + + // Check if the most recent call to 'setuid(getuid())' is assumed to be != 0. + // It should be only -1 at failure, but we want to accept a "!= 0" check too. + // (But now an invalid failure check like "!= 1" will be recognized as correct + // too. The "invalid failure check" is a different bug that is not the scope + // of this checker.) + auto FailComparison = + SVB.evalBinOpNN(State, BO_NE, nonloc::SymbolVal(LastSetuidSym), + SVB.makeIntVal(0, /*isUnsigned=*/false), + SVB.getConditionType()) + .getAs(); + if (!FailComparison) + return State; + if (auto IsFailBranch = State->assume(*FailComparison); + IsFailBranch.first && !IsFailBranch.second) { + // This is the 'setuid(getuid())' != 0 case. + // On this branch we do not want to emit warning. + State = State->set(Irrelevant); + State = State->set(SymbolRef{}); + } + return State; +} + +void SetgidSetuidOrderChecker::processSetuid(ProgramStateRef State, + const CallEvent &Call, + CheckerContext &C) const { + bool IsSetuidWithGetuid = isFunctionCalledInArg(GetuidDesc, Call); + if (State->get() != Setgid && IsSetuidWithGetuid) { + SymbolRef RetSym = Call.getReturnValue().getAsSymbol(); + State = State->set(Setuid); + State = State->set(RetSym); + const NoteTag *Note = C.getNoteTag([this, + RetSym](PathSensitiveBugReport &BR) { + if (!BR.isInteresting(RetSym) || &BR.getBugType() != &this->BT) + return ""; + return "Call to 'setuid' found here that removes superuser privileges"; + }); + C.addTransition(State, Note); + return; + } + State = State->set(Irrelevant); + State = State->set(SymbolRef{}); + C.addTransition(State); +} + +void SetgidSetuidOrderChecker::processSetgid(ProgramStateRef State, + const CallEvent &Call, + CheckerContext &C) const { + bool IsSetgidWithGetgid = isFunctionCalledInArg(GetgidDesc, Call); + if (State->get() == Setuid) { + if (IsSetgidWithGetgid) { + State = State->set(Irrelevant); + emitReport(State, C); + return; + } + State = State->set(Irrelevant); + } else { + State = State->set(IsSetgidWithGetgid ? Setgid + : Irrelevant); + } + State = State->set(SymbolRef{}); + C.addTransition(State); +} + +void SetgidSetuidOrderChecker::processOther(ProgramStateRef State, + const CallEvent &Call, + CheckerContext &C) const { + State = State->set(SymbolRef{}); + State = State->set(Irrelevant); + C.addTransition(State); +} + +bool SetgidSetuidOrderChecker::isFunctionCalledInArg( + const CallDescription &Desc, const CallEvent &Call) const { + if (const auto *CallInArg0 = + dyn_cast(Call.getArgExpr(0)->IgnoreParenImpCasts())) + return Desc.matchesAsWritten(*CallInArg0); + return false; +} + +void SetgidSetuidOrderChecker::emitReport(ProgramStateRef State, + CheckerContext &C) const { + if (ExplodedNode *N = C.generateNonFatalErrorNode(State)) { + llvm::StringLiteral Msg = + "A 'setgid(getgid())' call following a 'setuid(getuid())' " + "call is likely to fail; probably the order of these " + "statements is wrong"; + auto Report = std::make_unique(BT, Msg, N); + Report->markInteresting(State->get()); + C.emitReport(std::move(Report)); + } +} + +void ento::registerSetgidSetuidOrderChecker(CheckerManager &mgr) { + mgr.registerChecker(); +} + +bool ento::shouldRegisterSetgidSetuidOrderChecker(const CheckerManager &mgr) { + return true; +} diff --git a/clang/test/Analysis/setgid-setuid-order-notes.c b/clang/test/Analysis/setgid-setuid-order-notes.c new file mode 100644 index 000000000000..03402413581c --- /dev/null +++ b/clang/test/Analysis/setgid-setuid-order-notes.c @@ -0,0 +1,73 @@ +// RUN: %clang_analyze_cc1 -analyzer-checker=core,security.SetgidSetuidOrder -analyzer-output=text -verify %s + +typedef int uid_t; +typedef int gid_t; + +int setuid(uid_t); +int setgid(gid_t); + +uid_t getuid(); +gid_t getgid(); + + + +void test_note_1() { + if (setuid(getuid()) == -1) // expected-note{{Assuming the condition is false}} \ + // expected-note{{Taking false branch}} + return; + if (setuid(getuid()) == -1) // expected-note{{Call to 'setuid' found here that removes superuser privileges}} \ + // expected-note{{Assuming the condition is false}} \ + // expected-note{{Taking false branch}} + return; + if (setgid(getgid()) == -1) // expected-warning{{A 'setgid(getgid())' call following a 'setuid(getuid())' call is likely to fail}} \ + // expected-note{{A 'setgid(getgid())' call following a 'setuid(getuid())' call is likely to fail}} + return; +} + +void test_note_2() { + if (setuid(getuid()) == -1) // expected-note{{Call to 'setuid' found here that removes superuser privileges}} \ + // expected-note 2 {{Assuming the condition is false}} \ + // expected-note 2 {{Taking false branch}} + return; + if (setgid(getgid()) == -1) // expected-warning{{A 'setgid(getgid())' call following a 'setuid(getuid())' call is likely to fail}} \ + // expected-note{{A 'setgid(getgid())' call following a 'setuid(getuid())' call is likely to fail}} \ + // expected-note{{Assuming the condition is false}} \ + // expected-note{{Taking false branch}} + return; + if (setuid(getuid()) == -1) // expected-note{{Call to 'setuid' found here that removes superuser privileges}} \ + // expected-note{{Assuming the condition is false}} \ + // expected-note{{Taking false branch}} + return; + if (setgid(getgid()) == -1) // expected-warning{{A 'setgid(getgid())' call following a 'setuid(getuid())' call is likely to fail}} \ + // expected-note{{A 'setgid(getgid())' call following a 'setuid(getuid())' call is likely to fail}} + return; +} + +int f_setuid() { + return setuid(getuid()); // expected-note{{Call to 'setuid' found here that removes superuser privileges}} +} + +int f_setgid() { + return setgid(getgid()); // expected-warning{{A 'setgid(getgid())' call following a 'setuid(getuid())' call is likely to fail}} \ + // expected-note{{A 'setgid(getgid())' call following a 'setuid(getuid())' call is likely to fail}} +} + +void test_note_3() { + if (f_setuid() == -1) // expected-note{{Assuming the condition is false}} \ + // expected-note{{Calling 'f_setuid'}} \ + // expected-note{{Returning from 'f_setuid'}} \ + // expected-note{{Taking false branch}} + return; + if (f_setgid() == -1) // expected-note{{Calling 'f_setgid'}} + return; +} + +void test_note_4() { + if (setuid(getuid()) == 0) { // expected-note{{Assuming the condition is true}} \ + // expected-note{{Call to 'setuid' found here that removes superuser privileges}} \ + // expected-note{{Taking true branch}} + if (setgid(getgid()) == 0) { // expected-warning{{A 'setgid(getgid())' call following a 'setuid(getuid())' call is likely to fail}} \ + // expected-note{{A 'setgid(getgid())' call following a 'setuid(getuid())' call is likely to fail}} + } + } +} diff --git a/clang/test/Analysis/setgid-setuid-order.c b/clang/test/Analysis/setgid-setuid-order.c new file mode 100644 index 000000000000..1c411aa6a27b --- /dev/null +++ b/clang/test/Analysis/setgid-setuid-order.c @@ -0,0 +1,257 @@ +// RUN: %clang_analyze_cc1 -analyzer-checker=core,security.SetgidSetuidOrder -verify %s + +typedef int uid_t; +typedef int gid_t; + +int setuid(uid_t); +int setgid(gid_t); +int seteuid(uid_t); +int setegid(gid_t); +int setreuid(uid_t, uid_t); +int setregid(gid_t, gid_t); +int setresuid(uid_t, uid_t, uid_t); +int setresgid(gid_t, gid_t, gid_t); + +uid_t getuid(); +gid_t getgid(); + + + +void correct_order() { + // A correct revocation sequence starts here. + if (setgid(getgid()) == -1) + return; + if (setuid(getuid()) == -1) + return; + // No warning for the following setgid statement. + // The previous setgid and setuid calls are a correct privilege revocation + // sequence. The checker does not care about the following statements (except + // if a wrong setuid-setgid sequence follows again). + if (setgid(getgid()) == -1) + return; +} + +void incorrect_after_correct() { + if (setgid(getgid()) == -1) + return; + if (setuid(getuid()) == -1) + return; + // Incorrect sequence starts here. + if (setuid(getuid()) == -1) + return; + if (setgid(getgid()) == -1) // expected-warning{{A 'setgid(getgid())' call following a 'setuid(getuid())' call is likely to fail}} + return; +} + +void incorrect_order() { + if (setuid(getuid()) == -1) + return; + if (setgid(getgid()) == -1) // expected-warning{{A 'setgid(getgid())' call following a 'setuid(getuid())' call is likely to fail}} + return; + if (setgid(getgid()) == -1) + return; +} + +void warn_at_second_time() { + if (setuid(getuid()) == -1) + return; + if (setgid(getgid()) == -1) // expected-warning{{A 'setgid(getgid())' call following a 'setuid(getuid())' call is likely to fail}} + return; + if (setuid(getuid()) == -1) + return; + if (setgid(getgid()) == -1) // expected-warning{{A 'setgid(getgid())' call following a 'setuid(getuid())' call is likely to fail}} + return; +} + +uid_t f_uid(); +gid_t f_gid(); + +void setuid_other() { + if (setuid(f_uid()) == -1) + return; + if (setgid(getgid()) == -1) + return; +} + +void setgid_other() { + if (setuid(getuid()) == -1) + return; + if (setgid(f_gid()) == -1) + return; + if (setgid(getgid()) == -1) + return; +} + +void setuid_other_between() { + if (setuid(getuid()) == -1) + return; + if (setuid(f_uid()) == -1) + return; + if (setgid(getgid()) == -1) + return; +} + +void setgid_with_getuid() { + if (setuid(getuid()) == -1) + return; + // add a clang-tidy check for this case? + if (setgid(getuid()) == -1) + return; +} + +void setuid_with_getgid() { + // add a clang-tidy check for this case? + if (setuid(getgid()) == -1) + return; + if (setgid(getgid()) == -1) + return; +} + +int f_setuid() { + return setuid(getuid()); +} + +int f_setgid() { + return setgid(getgid()); // expected-warning{{A 'setgid(getgid())' call following a 'setuid(getuid())' call is likely to fail}} +} + +void function_calls() { + if (f_setuid() == -1) + return; + if (f_setgid() == -1) + return; +} + +void seteuid_between() { + if (setuid(getuid()) == -1) + return; + if (seteuid(getuid()) == -1) + return; + if (setgid(getgid()) == -1) + return; +} + +void setegid_between() { + if (setuid(getuid()) == -1) + return; + if (setegid(getgid()) == -1) + return; + if (setgid(getgid()) == -1) + return; +} + +void setreuid_between() { + if (setuid(getuid()) == -1) + return; + if (setreuid(getuid(), getuid()) == -1) + return; + if (setgid(getgid()) == -1) + return; +} + +void setregid_between() { + if (setuid(getuid()) == -1) + return; + if (setregid(getgid(), getgid()) == -1) + return; + if (setgid(getgid()) == -1) + return; +} + +void setresuid_between() { + if (setuid(getuid()) == -1) + return; + if (setresuid(getuid(), getuid(), getuid()) == -1) + return; + if (setgid(getgid()) == -1) + return; +} + +void setresgid_between() { + if (setuid(getuid()) == -1) + return; + if (setresgid(getgid(), getgid(), getgid()) == -1) + return; + if (setgid(getgid()) == -1) + return; +} + +void getgid_getuid_between() { + if (setuid(getuid()) == -1) + return; + (void)getgid(); + (void)getuid(); + if (setgid(getgid()) == -1) // expected-warning{{A 'setgid(getgid())' call following a 'setuid(getuid())' call is likely to fail}} + return; +} + +void stored_getgid_getuid() { + // possible future improvement: detect this case + uid_t u = getuid(); + gid_t g = getgid(); + if (setuid(u) == -1) + return; + if (setgid(g) == -1) // no warning + return; +} + +void f_extern(); + +void other_unknown_function_between() { + if (setuid(getuid()) == -1) + return; + f_extern(); + if (setgid(getgid()) == -1) // expected-warning{{A 'setgid(getgid())' call following a 'setuid(getuid())' call is likely to fail}} + return; +} + +void setuid_error_case() { + if (setuid(getuid()) == -1) { + // No warning if we know that the first setuid call has failed. + (void)setgid(getgid()); + return; + } + (void)setgid(getgid()); // expected-warning{{A 'setgid(getgid())' call following a 'setuid(getuid())' call is likely to fail}} +} + +void setuid_success_case() { + if (setuid(getuid()) == 0) { + if (setgid(getgid()) == 0) { // expected-warning{{A 'setgid(getgid())' call following a 'setuid(getuid())' call is likely to fail}} + } + } +} + +void incorrect_order_compare_zero() { + if (setuid(getuid()) != 0) + return; + (void)setgid(getgid()); // expected-warning{{A 'setgid(getgid())' call following a 'setuid(getuid())' call is likely to fail}} +} + +void setuid_error_case_compare_zero() { + if (setuid(getuid()) != 0) { + // No warning if we know that the first setuid call has failed. + (void)setgid(getgid()); + return; + } +} + +void incorrect_order_compare_other() { + if (setuid(getuid()) == -2) { + // This is a case for improvement: + // The checker does not recognize that this is an invalid error check, + // but this is really another type of bug not related to this checker. + (void)setgid(getgid()); // warning should appear here + return; + } + if (setgid(getgid()) == -2) { // expected-warning{{A 'setgid(getgid())' call following a 'setuid(getuid())' call is likely to fail}} + return; + } +} + +const int FAIL = -1; + +void incorrect_order_compare_var() { + if (setuid(getuid()) == FAIL) + return; + (void)setgid(getgid()); // expected-warning{{A 'setgid(getgid())' call following a 'setuid(getuid())' call is likely to fail}} +} -- GitLab From 5cb2ea5704c733102ae93a50b10b80c1ae06112e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timm=20B=C3=A4der?= Date: Tue, 21 May 2024 12:55:02 +0200 Subject: [PATCH 099/452] [clang][Interp][NFC] Remove VarDecl requirement in diagnoseUnknownDecl() We can call diagnoseNonConstVariable() for all ValueDecls just fine. --- clang/lib/AST/Interp/Interp.cpp | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/clang/lib/AST/Interp/Interp.cpp b/clang/lib/AST/Interp/Interp.cpp index 3e4da487e43c..1ed2ff30bdd0 100644 --- a/clang/lib/AST/Interp/Interp.cpp +++ b/clang/lib/AST/Interp/Interp.cpp @@ -76,18 +76,15 @@ static bool diagnoseUnknownDecl(InterpState &S, CodePtr OpPC, } else { S.FFDiag(E); } - } else if (const auto *VD = dyn_cast(D)) { - if (!VD->getType().isConstQualified()) { - diagnoseNonConstVariable(S, OpPC, VD); - return false; - } - - // const, but no initializer. - if (!VD->getAnyInitializer()) { - diagnoseMissingInitializer(S, OpPC, VD); - return false; - } + return false; } + + if (!D->getType().isConstQualified()) + diagnoseNonConstVariable(S, OpPC, D); + else if (const auto *VD = dyn_cast(D); + VD && !VD->getAnyInitializer()) + diagnoseMissingInitializer(S, OpPC, VD); + return false; } -- GitLab From e5936b245e9af0cea69a7e4eae22a05b7ffcf5a3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timm=20B=C3=A4der?= Date: Tue, 21 May 2024 12:57:55 +0200 Subject: [PATCH 100/452] [clang][Interp][NFC] Fix toAPValue() for array root pointers isArrayElement() returns false for them, so we used to add the decl to the path, causing wrong APValues to be generated. --- clang/lib/AST/Interp/Pointer.cpp | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/clang/lib/AST/Interp/Pointer.cpp b/clang/lib/AST/Interp/Pointer.cpp index ee8cedccb8d4..e45c291668ca 100644 --- a/clang/lib/AST/Interp/Pointer.cpp +++ b/clang/lib/AST/Interp/Pointer.cpp @@ -144,13 +144,18 @@ APValue Pointer::toAPValue() const { // TODO: compute the offset into the object. CharUnits Offset = CharUnits::Zero(); - bool IsOnePastEnd = isOnePastEnd(); // Build the path into the object. Pointer Ptr = *this; while (Ptr.isField() || Ptr.isArrayElement()) { - if (Ptr.isArrayElement()) { - Path.push_back(APValue::LValuePathEntry::ArrayIndex(Ptr.getIndex())); + if (Ptr.isArrayRoot()) { + Path.push_back(APValue::LValuePathEntry::ArrayIndex(0)); + Ptr = Ptr.getBase(); + } else if (Ptr.isArrayElement()) { + if (Ptr.isOnePastEnd()) + Path.push_back(APValue::LValuePathEntry::ArrayIndex(Ptr.getArray().getNumElems())); + else + Path.push_back(APValue::LValuePathEntry::ArrayIndex(Ptr.getIndex())); Ptr = Ptr.getArray(); } else { // TODO: figure out if base is virtual @@ -173,7 +178,7 @@ APValue Pointer::toAPValue() const { // Just invert the order of the elements. std::reverse(Path.begin(), Path.end()); - return APValue(Base, Offset, Path, IsOnePastEnd, /*IsNullPtr=*/false); + return APValue(Base, Offset, Path, /*IsOnePastEnd=*/false, /*IsNullPtr=*/false); } void Pointer::print(llvm::raw_ostream &OS) const { -- GitLab From 9807f25baa98be3bcce579302b2348b8abaf5cbd Mon Sep 17 00:00:00 2001 From: Tom Eccles Date: Wed, 22 May 2024 11:32:40 +0100 Subject: [PATCH 101/452] [flang][HLFIR] Adapt OptimizedBufferization to run on all top level ops (#92898) This means that this pass will also run on hlfir elemental operations which are not inside of functions. See RFC: https://discourse.llvm.org/t/rfc-add-an-interface-for-top-level-container-operations Some of the changes are from moving the declaration and definition of the constructor into tablegen (as requested during code review of another pass). --- flang/include/flang/Optimizer/HLFIR/Passes.h | 1 - flang/include/flang/Optimizer/HLFIR/Passes.td | 3 +-- flang/include/flang/Tools/CLOptions.inc | 3 ++- .../HLFIR/Transforms/OptimizedBufferization.cpp | 9 ++------- flang/test/Driver/mlir-pass-pipeline.f90 | 7 +++++++ flang/test/Fir/basic-program.fir | 9 ++++++++- 6 files changed, 20 insertions(+), 12 deletions(-) diff --git a/flang/include/flang/Optimizer/HLFIR/Passes.h b/flang/include/flang/Optimizer/HLFIR/Passes.h index f0736c782b6c..5035415ede2d 100644 --- a/flang/include/flang/Optimizer/HLFIR/Passes.h +++ b/flang/include/flang/Optimizer/HLFIR/Passes.h @@ -26,7 +26,6 @@ std::unique_ptr createConvertHLFIRtoFIRPass(); std::unique_ptr createBufferizeHLFIRPass(); std::unique_ptr createLowerHLFIRIntrinsicsPass(); std::unique_ptr createLowerHLFIROrderedAssignmentsPass(); -std::unique_ptr createOptimizedBufferizationPass(); #define GEN_PASS_REGISTRATION #include "flang/Optimizer/HLFIR/Passes.h.inc" diff --git a/flang/include/flang/Optimizer/HLFIR/Passes.td b/flang/include/flang/Optimizer/HLFIR/Passes.td index 0d4496a44c20..0fe2d9c0a632 100644 --- a/flang/include/flang/Optimizer/HLFIR/Passes.td +++ b/flang/include/flang/Optimizer/HLFIR/Passes.td @@ -23,9 +23,8 @@ def BufferizeHLFIR : Pass<"bufferize-hlfir", "::mlir::ModuleOp"> { let constructor = "hlfir::createBufferizeHLFIRPass()"; } -def OptimizedBufferization : Pass<"opt-bufferization", "::mlir::func::FuncOp"> { +def OptimizedBufferization : Pass<"opt-bufferization"> { let summary = "Special cases for hlfir.expr bufferization where we can avoid a temporary which would be created by the generic bufferization pass"; - let constructor = "hlfir::createOptimizedBufferizationPass()"; } def LowerHLFIRIntrinsics : Pass<"lower-hlfir-intrinsics", "::mlir::ModuleOp"> { diff --git a/flang/include/flang/Tools/CLOptions.inc b/flang/include/flang/Tools/CLOptions.inc index 3900b172917e..82a8aece8275 100644 --- a/flang/include/flang/Tools/CLOptions.inc +++ b/flang/include/flang/Tools/CLOptions.inc @@ -324,7 +324,8 @@ inline void createHLFIRToFIRPassPipeline( if (optLevel.isOptimizingForSpeed()) { addCanonicalizerPassWithoutRegionSimplification(pm); pm.addPass(mlir::createCSEPass()); - pm.addPass(hlfir::createOptimizedBufferizationPass()); + addNestedPassToAllTopLevelOperations( + pm, hlfir::createOptimizedBufferization); } pm.addPass(hlfir::createLowerHLFIROrderedAssignmentsPass()); pm.addPass(hlfir::createLowerHLFIRIntrinsicsPass()); diff --git a/flang/lib/Optimizer/HLFIR/Transforms/OptimizedBufferization.cpp b/flang/lib/Optimizer/HLFIR/Transforms/OptimizedBufferization.cpp index 8d68c7021608..3c8424ca564e 100644 --- a/flang/lib/Optimizer/HLFIR/Transforms/OptimizedBufferization.cpp +++ b/flang/lib/Optimizer/HLFIR/Transforms/OptimizedBufferization.cpp @@ -1038,7 +1038,6 @@ class OptimizedBufferizationPass OptimizedBufferizationPass> { public: void runOnOperation() override { - mlir::func::FuncOp func = getOperation(); mlir::MLIRContext *context = &getContext(); mlir::GreedyRewriteConfig config; @@ -1062,15 +1061,11 @@ public: patterns.insert>(context); if (mlir::failed(mlir::applyPatternsAndFoldGreedily( - func, std::move(patterns), config))) { - mlir::emitError(func.getLoc(), + getOperation(), std::move(patterns), config))) { + mlir::emitError(getOperation()->getLoc(), "failure in HLFIR optimized bufferization"); signalPassFailure(); } } }; } // namespace - -std::unique_ptr hlfir::createOptimizedBufferizationPass() { - return std::make_unique(); -} diff --git a/flang/test/Driver/mlir-pass-pipeline.f90 b/flang/test/Driver/mlir-pass-pipeline.f90 index 6d0e6c3bdcce..b3712db4ac61 100644 --- a/flang/test/Driver/mlir-pass-pipeline.f90 +++ b/flang/test/Driver/mlir-pass-pipeline.f90 @@ -30,8 +30,15 @@ end program ! O2-NEXT: CSE ! O2-NEXT: (S) {{.*}} num-cse'd ! O2-NEXT: (S) {{.*}} num-dce'd +! O2-NEXT: Pipeline Collection : ['fir.global', 'func.func', 'omp.declare_reduction', 'omp.private'] +! O2-NEXT: 'fir.global' Pipeline +! O2-NEXT: OptimizedBufferization ! O2-NEXT: 'func.func' Pipeline ! O2-NEXT: OptimizedBufferization +! O2-NEXT: 'omp.declare_reduction' Pipeline +! O2-NEXT: OptimizedBufferization +! O2-NEXT: 'omp.private' Pipeline +! O2-NEXT: OptimizedBufferization ! ALL: LowerHLFIROrderedAssignments ! ALL-NEXT: LowerHLFIRIntrinsics ! ALL-NEXT: BufferizeHLFIR diff --git a/flang/test/Fir/basic-program.fir b/flang/test/Fir/basic-program.fir index 42bceb66668d..db252c4adfd4 100644 --- a/flang/test/Fir/basic-program.fir +++ b/flang/test/Fir/basic-program.fir @@ -34,7 +34,14 @@ func.func @_QQmain() { // PASSES-NEXT: CSE // PASSES-NEXT: (S) 0 num-cse'd - Number of operations CSE'd // PASSES-NEXT: (S) 0 num-dce'd - Number of operations DCE'd -// PASSES-NEXT: 'func.func' Pipeline +// PASSES-NEXT: Pipeline Collection : ['fir.global', 'func.func', 'omp.declare_reduction', 'omp.private'] +// PASSES-NEXT: 'fir.global' Pipeline +// PASSES-NEXT: OptimizedBufferization +// PASSES-NEXT: 'func.func' Pipeline +// PASSES-NEXT: OptimizedBufferization +// PASSES-NEXT: 'omp.declare_reduction' Pipeline +// PASSES-NEXT: OptimizedBufferization +// PASSES-NEXT: 'omp.private' Pipeline // PASSES-NEXT: OptimizedBufferization // PASSES-NEXT: LowerHLFIROrderedAssignments // PASSES-NEXT: LowerHLFIRIntrinsics -- GitLab From 3c5738f3ec185fbf56da2c18929f5b33126cd98b Mon Sep 17 00:00:00 2001 From: Carlos Alberto Enciso Date: Wed, 22 May 2024 11:36:10 +0100 Subject: [PATCH 102/452] Revert "[indvars] Missing variables at Og (#88270)" (#93016) This reverts commit 89e1f7784be40bea96d5e65919ce8d34151c1d69. https://github.com/llvm/llvm-project/pull/88270#discussion_r1609559724 https://github.com/llvm/llvm-project/pull/88270#discussion_r1609552972 Main concerns from @nikic are the interaction between the 'IndVars' and 'LoopDeletion' passes, increasing build times and adding extra complexity. --- llvm/include/llvm/Analysis/LoopInfo.h | 25 ---- .../include/llvm/Transforms/Utils/LoopUtils.h | 6 - llvm/lib/Transforms/Utils/LoopUtils.cpp | 65 --------- .../Transforms/IndVarSimplify/pr51735-1.ll | 129 ----------------- .../Transforms/IndVarSimplify/pr51735-2.ll | 128 ----------------- .../Transforms/IndVarSimplify/pr51735-3.ll | 131 ------------------ .../test/Transforms/IndVarSimplify/pr51735.ll | 104 -------------- 7 files changed, 588 deletions(-) delete mode 100644 llvm/test/Transforms/IndVarSimplify/pr51735-1.ll delete mode 100644 llvm/test/Transforms/IndVarSimplify/pr51735-2.ll delete mode 100644 llvm/test/Transforms/IndVarSimplify/pr51735-3.ll delete mode 100644 llvm/test/Transforms/IndVarSimplify/pr51735.ll diff --git a/llvm/include/llvm/Analysis/LoopInfo.h b/llvm/include/llvm/Analysis/LoopInfo.h index 28c888f0c9a1..52084630560c 100644 --- a/llvm/include/llvm/Analysis/LoopInfo.h +++ b/llvm/include/llvm/Analysis/LoopInfo.h @@ -17,9 +17,7 @@ #include "llvm/ADT/SmallVector.h" #include "llvm/IR/CFG.h" #include "llvm/IR/Instructions.h" -#include "llvm/IR/IntrinsicInst.h" #include "llvm/IR/PassManager.h" -#include "llvm/IR/ValueHandle.h" #include "llvm/Pass.h" #include "llvm/Support/GenericLoopInfo.h" #include @@ -394,22 +392,6 @@ public: return ""; } - /// Preserve the induction variable exit value and its debug users by the - /// 'indvars' pass if the loop can deleted. Those debug users will be used - /// by the 'loop-delete' pass. - void preserveDebugInductionVariableInfo( - Value *FinalValue, - const SmallVectorImpl &DbgUsers) { - IndVarFinalValue = FinalValue; - for (auto &DebugUser : DbgUsers) - IndVarDebugUsers.push_back(DebugUser); - } - - Value *getDebugInductionVariableFinalValue() { return IndVarFinalValue; } - SmallVector &getDebugInductionVariableDebugUsers() { - return IndVarDebugUsers; - } - private: Loop() = default; @@ -417,13 +399,6 @@ private: friend class LoopBase; explicit Loop(BasicBlock *BB) : LoopBase(BB) {} ~Loop() = default; - - // Induction variable exit value and its debug users, preserved by the - // 'indvars' pass, when it detects that the loop can be deleted and the - // there are no PHIs to be rewritten. - // For now, we only preserve single induction variables. - Value *IndVarFinalValue = nullptr; - SmallVector IndVarDebugUsers; }; // Implementation in Support/GenericLoopInfoImpl.h diff --git a/llvm/include/llvm/Transforms/Utils/LoopUtils.h b/llvm/include/llvm/Transforms/Utils/LoopUtils.h index 15b230ba92dd..345e09dce0b2 100644 --- a/llvm/include/llvm/Transforms/Utils/LoopUtils.h +++ b/llvm/include/llvm/Transforms/Utils/LoopUtils.h @@ -468,12 +468,6 @@ int rewriteLoopExitValues(Loop *L, LoopInfo *LI, TargetLibraryInfo *TLI, ReplaceExitVal ReplaceExitValue, SmallVector &DeadInsts); -/// Assign exit values to variables that use this loop variable during the loop. -void addDebugValuesToIncomingValue(BasicBlock *Successor, Value *IndVar, - PHINode *PN); -void addDebugValuesToLoopVariable(BasicBlock *Successor, Value *ExitValue, - PHINode *PN); - /// Set weights for \p UnrolledLoop and \p RemainderLoop based on weights for /// \p OrigLoop and the following distribution of \p OrigLoop iteration among \p /// UnrolledLoop and \p RemainderLoop. \p UnrolledLoop receives weights that diff --git a/llvm/lib/Transforms/Utils/LoopUtils.cpp b/llvm/lib/Transforms/Utils/LoopUtils.cpp index 0bd1e8ab1d39..cc883a7dc292 100644 --- a/llvm/lib/Transforms/Utils/LoopUtils.cpp +++ b/llvm/lib/Transforms/Utils/LoopUtils.cpp @@ -31,7 +31,6 @@ #include "llvm/Analysis/ScalarEvolutionAliasAnalysis.h" #include "llvm/Analysis/ScalarEvolutionExpressions.h" #include "llvm/IR/DIBuilder.h" -#include "llvm/IR/DebugInfo.h" #include "llvm/IR/Dominators.h" #include "llvm/IR/Instructions.h" #include "llvm/IR/IntrinsicInst.h" @@ -609,17 +608,6 @@ void llvm::deleteDeadLoop(Loop *L, DominatorTree *DT, ScalarEvolution *SE, llvm::SmallVector DeadDbgVariableRecords; if (ExitBlock) { - if (ExitBlock->phis().empty()) { - // As the loop is deleted, replace the debug users with the preserved - // induction variable final value recorded by the 'indvar' pass. - Value *FinalValue = L->getDebugInductionVariableFinalValue(); - SmallVector &DbgUsers = L->getDebugInductionVariableDebugUsers(); - for (WeakVH &DebugUser : DbgUsers) - if (DebugUser) - cast(DebugUser)->replaceVariableLocationOp( - 0u, FinalValue); - } - // Given LCSSA form is satisfied, we should not have users of instructions // within the dead loop outside of the loop. However, LCSSA doesn't take // unreachable uses into account. We handle them here. @@ -1413,36 +1401,6 @@ static bool checkIsIndPhi(PHINode *Phi, Loop *L, ScalarEvolution *SE, return InductionDescriptor::isInductionPHI(Phi, L, SE, ID); } -void llvm::addDebugValuesToIncomingValue(BasicBlock *Successor, Value *IndVar, - PHINode *PN) { - SmallVector DbgUsers; - findDbgUsers(DbgUsers, IndVar); - for (auto *DebugUser : DbgUsers) { - // Skip debug-users with variadic variable locations; they will not, - // get updated, which is fine as that is the existing behaviour. - if (DebugUser->hasArgList()) - continue; - auto *Cloned = cast(DebugUser->clone()); - Cloned->replaceVariableLocationOp(0u, PN); - Cloned->insertBefore(*Successor, Successor->getFirstNonPHIIt()); - } -} - -void llvm::addDebugValuesToLoopVariable(BasicBlock *Successor, Value *ExitValue, - PHINode *PN) { - SmallVector DbgUsers; - findDbgUsers(DbgUsers, PN); - for (auto *DebugUser : DbgUsers) { - // Skip debug-users with variadic variable locations; they will not, - // get updated, which is fine as that is the existing behaviour. - if (DebugUser->hasArgList()) - continue; - auto *Cloned = cast(DebugUser->clone()); - Cloned->replaceVariableLocationOp(0u, ExitValue); - Cloned->insertBefore(*Successor, Successor->getFirstNonPHIIt()); - } -} - int llvm::rewriteLoopExitValues(Loop *L, LoopInfo *LI, TargetLibraryInfo *TLI, ScalarEvolution *SE, const TargetTransformInfo *TTI, @@ -1584,10 +1542,6 @@ int llvm::rewriteLoopExitValues(Loop *L, LoopInfo *LI, TargetLibraryInfo *TLI, (isa(Inst) || isa(Inst)) ? &*Inst->getParent()->getFirstInsertionPt() : Inst; RewritePhiSet.emplace_back(PN, i, ExitValue, InsertPt, HighCost); - - // Add debug values for the candidate PHINode incoming value. - if (BasicBlock *Successor = ExitBB->getSingleSuccessor()) - addDebugValuesToIncomingValue(Successor, PN->getIncomingValue(i), PN); } } } @@ -1646,30 +1600,11 @@ int llvm::rewriteLoopExitValues(Loop *L, LoopInfo *LI, TargetLibraryInfo *TLI, // Replace PN with ExitVal if that is legal and does not break LCSSA. if (PN->getNumIncomingValues() == 1 && LI->replacementPreservesLCSSAForm(PN, ExitVal)) { - addDebugValuesToLoopVariable(PN->getParent(), ExitVal, PN); PN->replaceAllUsesWith(ExitVal); PN->eraseFromParent(); } } - // If the loop can be deleted and there are no PHIs to be rewritten (there - // are no loop live-out values), record debug variables corresponding to the - // induction variable with their constant exit-values. Those values will be - // inserted by the 'deletion loop' logic. - if (LoopCanBeDel && RewritePhiSet.empty()) { - if (auto *IndVar = L->getInductionVariable(*SE)) { - const SCEV *PNSCEV = SE->getSCEVAtScope(IndVar, L->getParentLoop()); - if (auto *Const = dyn_cast(PNSCEV)) { - Value *FinalIVValue = Const->getValue(); - if (L->getUniqueExitBlock()) { - SmallVector DbgUsers; - findDbgUsers(DbgUsers, IndVar); - L->preserveDebugInductionVariableInfo(FinalIVValue, DbgUsers); - } - } - } - } - // The insertion point instruction may have been deleted; clear it out // so that the rewriter doesn't trip over it later. Rewriter.clearInsertPoint(); diff --git a/llvm/test/Transforms/IndVarSimplify/pr51735-1.ll b/llvm/test/Transforms/IndVarSimplify/pr51735-1.ll deleted file mode 100644 index 356217985fed..000000000000 --- a/llvm/test/Transforms/IndVarSimplify/pr51735-1.ll +++ /dev/null @@ -1,129 +0,0 @@ -; RUN: opt -passes="loop(indvars)" \ -; RUN: --experimental-debuginfo-iterators=false -S -o - < %s | \ -; RUN: FileCheck --check-prefix=CHECK %s -; RUN: opt -passes="loop(indvars,loop-deletion)" \ -; RUN: --experimental-debuginfo-iterators=false -S -o - < %s | \ -; RUN: FileCheck --check-prefix=CHECK %s - -; Make sure that when we delete the loop, that the variable Index has -; the 777 value. - -; As this test case does fire the 'indvars' transformation, the debug values -; are added to the 'for.end' exit block. No debug values are preserved by the -; pass to be used by the 'loop-deletion' pass. - -; CHECK: for.cond: -; CHECK: call void @llvm.dbg.value(metadata i32 %[[SSA_INDEX_0:.+]], metadata ![[DBG:[0-9]+]], {{.*}} - -; CHECK: for.extra: -; CHECK: %[[SSA_CALL_0:.+]] = call noundef i32 @"?nop@@YAHH@Z"(i32 noundef %[[SSA_INDEX_0]]), {{.*}} -; CHECK: br i1 %[[SSA_CMP_0:.+]], label %for.cond, label %if.else, {{.*}} - -; CHECK: if.then: -; CHECK: call void @llvm.dbg.value(metadata i32 777, metadata ![[DBG]], {{.*}} -; CHECK: call void @llvm.dbg.value(metadata i32 %[[SSA_VAR_1:.+]], metadata ![[VAR:[0-9]+]], {{.*}} -; CHECK: br label %for.end, {{.*}} - -; CHECK: if.else: -; CHECK: call void @llvm.dbg.value(metadata i32 %[[SSA_VAR_2:.+]], metadata ![[VAR:[0-9]+]], {{.*}} -; CHECK: br label %for.end, {{.*}} - -; CHECK: for.end: -; CHECK: call void @llvm.dbg.value(metadata i32 777, metadata ![[DBG]], {{.*}} - -; CHECK-DAG: ![[DBG]] = !DILocalVariable(name: "Index"{{.*}}) -; CHECK-DAG: ![[VAR]] = !DILocalVariable(name: "Var"{{.*}}) - -define dso_local noundef i32 @"?nop@@YAHH@Z"(i32 noundef %Param) !dbg !11 { -entry: - %Param.addr = alloca i32, align 4 - store i32 %Param, ptr %Param.addr, align 4 - call void @llvm.dbg.declare(metadata ptr %Param.addr, metadata !32, metadata !DIExpression()), !dbg !35 - ret i32 0, !dbg !36 -} - -define dso_local void @_Z3barv() local_unnamed_addr #1 !dbg !12 { -entry: - call void @llvm.dbg.value(metadata i32 777, metadata !16, metadata !DIExpression()), !dbg !17 - call void @llvm.dbg.value(metadata i32 27, metadata !18, metadata !DIExpression()), !dbg !17 - call void @llvm.dbg.value(metadata i32 1, metadata !19, metadata !DIExpression()), !dbg !17 - call void @llvm.dbg.value(metadata i32 1, metadata !30, metadata !DIExpression()), !dbg !17 - br label %for.cond, !dbg !20 - -for.cond: ; preds = %for.cond, %entry - %Index.0 = phi i32 [ 27, %entry ], [ %inc, %for.extra ], !dbg !17 - call void @llvm.dbg.value(metadata i32 %Index.0, metadata !18, metadata !DIExpression()), !dbg !17 - %cmp = icmp ult i32 %Index.0, 777, !dbg !21 - %inc = add nuw nsw i32 %Index.0, 1, !dbg !24 - call void @llvm.dbg.value(metadata i32 %inc, metadata !18, metadata !DIExpression()), !dbg !17 - br i1 %cmp, label %for.extra, label %if.then, !dbg !25, !llvm.loop !26 - -for.extra: - %call.0 = call noundef i32 @"?nop@@YAHH@Z"(i32 noundef %Index.0), !dbg !21 - %cmp.0 = icmp ult i32 %Index.0, %call.0, !dbg !21 - br i1 %cmp.0, label %for.cond, label %if.else, !dbg !25, !llvm.loop !26 - -if.then: ; preds = %for.cond - %Var.1 = add nsw i32 %Index.0, 1, !dbg !20 - call void @llvm.dbg.value(metadata i32 %Var.1, metadata !19, metadata !DIExpression()), !dbg !20 - br label %for.end, !dbg !20 - -if.else: - %Var.2 = add nsw i32 %Index.0, 2, !dbg !20 - call void @llvm.dbg.value(metadata i32 %Var.2, metadata !19, metadata !DIExpression()), !dbg !20 - br label %for.end, !dbg !20 - -for.end: ; preds = %if.else, %if.then - %Zeta.0 = phi i32 [ %Var.1, %if.then ], [ %Var.2, %if.else ], !dbg !20 - call void @llvm.dbg.value(metadata i32 %Zeta.0, metadata !30, metadata !DIExpression()), !dbg !20 - %Var.3 = add nsw i32 %Index.0, 1, !dbg !20 - call void @llvm.dbg.value(metadata i32 %Var.3, metadata !19, metadata !DIExpression()), !dbg !20 - %call = call noundef i32 @"?nop@@YAHH@Z"(i32 noundef %Index.0), !dbg !37 - ret void, !dbg !29 -} - -declare void @llvm.dbg.value(metadata, metadata, metadata) -declare void @llvm.dbg.declare(metadata, metadata, metadata) - -!llvm.dbg.cu = !{!0} -!llvm.module.flags = !{!2, !3, !4, !5, !6, !7, !8} -!llvm.ident = !{!9} - -!0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus_14, file: !1, producer: "clang", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, splitDebugInlining: false, nameTableKind: None) -!1 = !DIFile(filename: "test.cpp", directory: "") -!2 = !{i32 7, !"Dwarf Version", i32 5} -!3 = !{i32 2, !"Debug Info Version", i32 3} -!4 = !{i32 1, !"wchar_size", i32 4} -!5 = !{i32 8, !"PIC Level", i32 2} -!6 = !{i32 7, !"PIE Level", i32 2} -!7 = !{i32 7, !"uwtable", i32 2} -!8 = !{i32 7, !"frame-pointer", i32 2} -!9 = !{!"clang version 18.0.0"} -!10 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) -!11 = distinct !DISubprogram(name: "nop", linkageName: "?nop@@YAHH@Z", scope: !1, file: !1, line: 1, type: !33, scopeLine: 1, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !31) -!12 = distinct !DISubprogram(name: "bar", linkageName: "_Z3barv", scope: !1, file: !1, line: 5, type: !13, scopeLine: 5, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !0, retainedNodes: !15) -!13 = !DISubroutineType(types: !14) -!14 = !{null} -!15 = !{} -!16 = !DILocalVariable(name: "End", scope: !12, file: !1, line: 6, type: !10) -!17 = !DILocation(line: 0, scope: !12) -!18 = !DILocalVariable(name: "Index", scope: !12, file: !1, line: 7, type: !10) -!19 = !DILocalVariable(name: "Var", scope: !12, file: !1, line: 8, type: !10) -!20 = !DILocation(line: 9, column: 3, scope: !12) -!21 = !DILocation(line: 9, column: 16, scope: !22) -!22 = distinct !DILexicalBlock(scope: !23, file: !1, line: 9, column: 3) -!23 = distinct !DILexicalBlock(scope: !12, file: !1, line: 9, column: 3) -!24 = !DILocation(line: 9, column: 23, scope: !22) -!25 = !DILocation(line: 9, column: 3, scope: !23) -!26 = distinct !{!26, !25, !27, !28} -!27 = !DILocation(line: 10, column: 5, scope: !23) -!28 = !{!"llvm.loop.mustprogress"} -!29 = !DILocation(line: 12, column: 1, scope: !12) -!30 = !DILocalVariable(name: "Zeta", scope: !12, file: !1, line: 8, type: !10) -!31 = !{!32} -!32 = !DILocalVariable(name: "Param", arg: 1, scope: !11, file: !1, line: 1, type: !10) -!33 = !DISubroutineType(types: !34) -!34 = !{!10, !10} -!35 = !DILocation(line: 1, scope: !11) -!36 = !DILocation(line: 2, scope: !11) -!37 = !DILocation(line: 20, scope: !12) diff --git a/llvm/test/Transforms/IndVarSimplify/pr51735-2.ll b/llvm/test/Transforms/IndVarSimplify/pr51735-2.ll deleted file mode 100644 index 58cc9932e04c..000000000000 --- a/llvm/test/Transforms/IndVarSimplify/pr51735-2.ll +++ /dev/null @@ -1,128 +0,0 @@ -; RUN: opt -passes="loop(indvars)" \ -; RUN: --experimental-debuginfo-iterators=false -S -o - < %s | \ -; RUN: FileCheck --implicit-check-not="call void @llvm.dbg" \ -; RUN: --check-prefix=ALL-CHECK --check-prefix=PRE-CHECK %s -; RUN: opt -passes="loop(indvars,loop-deletion)" \ -; RUN: --experimental-debuginfo-iterators=false -S -o - < %s | \ -; RUN: FileCheck --implicit-check-not="call void @llvm.dbg" \ -; RUN: --check-prefix=ALL-CHECK --check-prefix=POST-CHECK %s - -; Check what happens to a modified but otherwise unused variable in a loop -; that gets deleted. The assignment in the loop is 'forgotten' by LLVM and -; doesn't appear in the debugging information. This behaviour is suboptimal, -; but we want to know if it changes - -; For all cases, LLDB shows -; Var = - -; 1 __attribute__((optnone)) int nop() { -; 2 return 0; -; 3 } -; 4 -; 5 void bar() { -; 6 int End = 777; -; 7 int Index = 27; -; 8 char Var = 1; -; 9 for (; Index < End; ++Index) { -; 10 if (Index == 666) { -; 11 ++Var; -; 12 } -; 13 } -; 14 nop(); -; 15 } - -; ALL-CHECK: entry: -; ALL-CHECK: call void @llvm.dbg.value(metadata i32 1, metadata ![[DBG:[0-9]+]], {{.*}} - -; Only the 'indvars' pass is executed. -; PRE-CHECK: for.cond: -; PRE-CHECK: call void @llvm.dbg.value(metadata i32 %[[SSA_VAR_0:.+]], metadata ![[DBG]], {{.*}} -; PRE-CHECK: call void @llvm.dbg.value(metadata !DIArgList{{.*}} - -; PRE-CHECK: for.body: -; PRE-CHECK: {{.*}} = icmp eq i32 %[[SSA_INDEX_0:.+]], 666 -; PRE-CHECK: {{.*}} = add nsw i32 %[[SSA_VAR_0]], 1 -; PRE-CHECK: {{.*}} = select i1 {{.*}}, i32 {{.*}}, i32 %[[SSA_VAR_0]] -; PRE-CHECK: call void @llvm.dbg.value(metadata i32 {{.*}}, metadata ![[DBG]], {{.*}} -; PRE-CHECK: br label %for.cond - -; PRE-CHECK: for.end: -; PRE-CHECK: ret void -; PRE-CHECK-DAG: ![[DBG]] = !DILocalVariable(name: "Var"{{.*}}) - -; The 'indvars' and 'loop-deletion' passes are executed. -; POST-CHECK: for.end: -; POST-CHECK: call void @llvm.dbg.value(metadata i32 undef, metadata ![[DBG:[0-9]+]], {{.*}} -; POST-CHECK: ret void -; POST-CHECK-DAG: ![[DBG]] = !DILocalVariable(name: "Var"{{.*}}) - -define dso_local void @_Z3barv() local_unnamed_addr !dbg !18 { -entry: - call void @llvm.dbg.value(metadata i32 1, metadata !24, metadata !DIExpression()), !dbg !22 - br label %for.cond, !dbg !25 - -for.cond: ; preds = %for.cond, %entry - %Index.0 = phi i32 [ 27, %entry ], [ %inc2, %for.body ], !dbg !22 - %Var.0 = phi i32 [ 1, %entry ], [ %spec.select, %for.body ], !dbg !22 - call void @llvm.dbg.value(metadata i32 %Var.0, metadata !24, metadata !DIExpression()), !dbg !22 - %cmp = icmp ult i32 %Index.0, 777, !dbg !26 - call void @llvm.dbg.value(metadata !DIArgList(i32 poison, i32 %Index.0), metadata !24, metadata !DIExpression(DW_OP_LLVM_arg, 0, DW_OP_LLVM_arg, 1, DW_OP_constu, 666, DW_OP_eq, DW_OP_LLVM_convert, 1, DW_ATE_unsigned, DW_OP_LLVM_convert, 32, DW_ATE_unsigned, DW_OP_plus, DW_OP_stack_value)), !dbg !22 - %inc2 = add nuw nsw i32 %Index.0, 1, !dbg !29 - br i1 %cmp, label %for.body, label %for.end, !dbg !30, !llvm.loop !31 - -for.body: ; preds = %for.cond - %cmp1 = icmp eq i32 %Index.0, 666, !dbg !30 - %inc = add nsw i32 %Var.0, 1 - %spec.select = select i1 %cmp1, i32 %inc, i32 %Var.0, !dbg !32 - call void @llvm.dbg.value(metadata i32 %spec.select, metadata !24, metadata !DIExpression()), !dbg !22 - br label %for.cond, !dbg !34, !llvm.loop !35 - -for.end: ; preds = %for.cond - ret void, !dbg !35 -} - -declare void @llvm.dbg.value(metadata, metadata, metadata) - -!llvm.dbg.cu = !{!0} -!llvm.module.flags = !{!2, !3, !4, !5, !6, !7, !8} -!llvm.ident = !{!9} - -!0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus_14, file: !1, producer: "clang", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, splitDebugInlining: false, nameTableKind: None) -!1 = !DIFile(filename: "test-b.cpp", directory: "") -!2 = !{i32 7, !"Dwarf Version", i32 5} -!3 = !{i32 2, !"Debug Info Version", i32 3} -!4 = !{i32 1, !"wchar_size", i32 4} -!5 = !{i32 8, !"PIC Level", i32 2} -!6 = !{i32 7, !"PIE Level", i32 2} -!7 = !{i32 7, !"uwtable", i32 2} -!8 = !{i32 7, !"frame-pointer", i32 2} -!9 = !{!"clang version 19.0.0"} -!10 = distinct !DISubprogram(name: "nop", linkageName: "_Z3nopi", scope: !1, file: !1, line: 1, type: !11, scopeLine: 1, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !0, retainedNodes: !14) -!11 = !DISubroutineType(types: !12) -!12 = !{!13, !13} -!13 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) -!14 = !{} -!15 = !DILocalVariable(name: "Param", arg: 1, scope: !10, file: !1, line: 1, type: !13) -!16 = !DILocation(line: 1, column: 38, scope: !10) -!17 = !DILocation(line: 2, column: 3, scope: !10) -!18 = distinct !DISubprogram(name: "bar", linkageName: "_Z3barv", scope: !1, file: !1, line: 5, type: !19, scopeLine: 5, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !0, retainedNodes: !14) -!19 = !DISubroutineType(types: !20) -!20 = !{null} -!22 = !DILocation(line: 0, scope: !18) -!24 = !DILocalVariable(name: "Var", scope: !18, file: !1, line: 8, type: !13) -!25 = !DILocation(line: 9, column: 3, scope: !18) -!26 = !DILocation(line: 9, column: 16, scope: !27) -!27 = distinct !DILexicalBlock(scope: !28, file: !1, line: 9, column: 3) -!28 = distinct !DILexicalBlock(scope: !18, file: !1, line: 9, column: 3) -!29 = !DILocation(line: 9, column: 23, scope: !27) -!30 = !DILocation(line: 9, column: 3, scope: !28) -!31 = distinct !{!31, !30, !32, !33} -!32 = !DILocation(line: 11, column: 9, scope: !28) -!33 = !{!"llvm.loop.mustprogress"} -!34 = !DILocation(line: 12, column: 3, scope: !18) -!35 = !DILocation(line: 13, column: 1, scope: !18) -!36 = distinct !DISubprogram(name: "main", scope: !1, file: !1, line: 15, type: !37, scopeLine: 15, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !0) -!37 = !DISubroutineType(types: !38) -!38 = !{!13} -!39 = !DILocation(line: 16, column: 3, scope: !36) -!40 = !DILocation(line: 17, column: 1, scope: !36) diff --git a/llvm/test/Transforms/IndVarSimplify/pr51735-3.ll b/llvm/test/Transforms/IndVarSimplify/pr51735-3.ll deleted file mode 100644 index ac9964743e0f..000000000000 --- a/llvm/test/Transforms/IndVarSimplify/pr51735-3.ll +++ /dev/null @@ -1,131 +0,0 @@ -; RUN: opt -passes="loop(indvars)" \ -; RUN: --experimental-debuginfo-iterators=false -S -o - < %s | \ -; RUN: FileCheck --implicit-check-not="call void @llvm.dbg" \ -; RUN: --check-prefix=ALL-CHECK --check-prefix=PRE-CHECK %s -; RUN: opt -passes="loop(indvars,loop-deletion)" \ -; RUN: --experimental-debuginfo-iterators=false -S -o - < %s | \ -; RUN: FileCheck --implicit-check-not="call void @llvm.dbg" \ -; RUN: --check-prefix=ALL-CHECK --check-prefix=POST-CHECK %s - -; Check what happens to a modified but otherwise unused variable in a loop -; that gets deleted. The assignment in the loop is 'forgotten' by LLVM and -; doesn't appear in the debugging information. This behaviour is suboptimal, -; but we want to know if it changes - -; For all cases, LLDB shows -; Var = - -; 1 __attribute__((optnone)) int nop() { -; 2 return 0; -; 3 } -; 4 -; 5 void bar() { -; 6 int End = 777; -; 7 int Index = 27; -; 8 char Var = 1; -; 9 for (; Index < End; ++Index) { -; 10 if (Index == 666) { -; 11 Var = 555; -; 12 } -; 13 } -; 14 nop(); -; 15 } - -; ALL-CHECK: entry: -; ALL-CHECK: call void @llvm.dbg.value(metadata i32 1, metadata ![[DBG:[0-9]+]], {{.*}} - -; Only the 'indvars' pass is executed. -; PRE-CHECK: if.then: -; PRE-CHECK: call void @llvm.dbg.value(metadata i32 555, metadata ![[DBG]], {{.*}} - -; PRE-CHECK: for.inc: -; PRE-CHECK: %[[SSA_VAR_0:.+]] = phi i32 [ 1, %for.body ], [ 555, %if.then ] -; PRE-CHECK: call void @llvm.dbg.value(metadata i32 %[[SSA_VAR_0]], metadata ![[DBG]], {{.*}} -; PRE-CHECK: {{.*}} = add nuw nsw i32 %[[SSA_INDEX_0:.+]], 1 -; PRE-CHECK: br label %for.cond - -; PRE-CHECK: for.end: -; PRE-CHECK: ret void -; PRE-CHECK-DAG: ![[DBG]] = !DILocalVariable(name: "Var"{{.*}}) - -; The 'indvars' and 'loop-deletion' passes are executed. -; POST-CHECK: for.end: -; POST-CHECK: call void @llvm.dbg.value(metadata i32 555, metadata ![[DBG]], {{.*}} -; POST-CHECK: ret void -; POST-CHECK-DAG: ![[DBG]] = !DILocalVariable(name: "Var"{{.*}}) - -define dso_local void @_Z3barv() local_unnamed_addr !dbg !18 { -entry: - call void @llvm.dbg.value(metadata i32 1, metadata !24, metadata !DIExpression()), !dbg !22 - br label %for.cond, !dbg !25 - -for.cond: ; preds = %for.inc, %entry - %Index.0 = phi i32 [ 27, %entry ], [ %inc, %for.inc ], !dbg !22 - %cmp = icmp ult i32 %Index.0, 777, !dbg !26 - br i1 %cmp, label %for.body, label %for.end, !dbg !30, !llvm.loop !29 - -for.body: ; preds = %for.cond - %cmp1 = icmp eq i32 %Index.0, 666, !dbg !30 - br i1 %cmp1, label %if.then, label %for.inc, !dbg !32 - -if.then: ; preds = %for.body - call void @llvm.dbg.value(metadata i32 555, metadata !24, metadata !DIExpression()), !dbg !22 - br label %for.inc, !dbg !34, !llvm.loop !32 - -for.inc: ; preds = %for.body, %if.then - %Var.0 = phi i32 [ 1, %for.body ], [ 555, %if.then ], !dbg !22 - call void @llvm.dbg.value(metadata i32 %Var.0, metadata !24, metadata !DIExpression()), !dbg !22 - %inc = add nuw nsw i32 %Index.0, 1, !dbg !29 - br label %for.cond, !dbg !34, !llvm.loop !35 - -for.end: ; preds = %for.cond - ret void, !dbg !35 -} - -declare void @llvm.dbg.value(metadata, metadata, metadata) - -!llvm.dbg.cu = !{!0} -!llvm.module.flags = !{!2, !3, !4, !5, !6, !7, !8} -!llvm.ident = !{!9} - -!0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus_14, file: !1, producer: "clang", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, splitDebugInlining: false, nameTableKind: None) -!1 = !DIFile(filename: "test-c.cpp", directory: "") -!2 = !{i32 7, !"Dwarf Version", i32 5} -!3 = !{i32 2, !"Debug Info Version", i32 3} -!4 = !{i32 1, !"wchar_size", i32 4} -!5 = !{i32 8, !"PIC Level", i32 2} -!6 = !{i32 7, !"PIE Level", i32 2} -!7 = !{i32 7, !"uwtable", i32 2} -!8 = !{i32 7, !"frame-pointer", i32 2} -!9 = !{!"clang version 19.0.0"} -!10 = distinct !DISubprogram(name: "nop", linkageName: "_Z3nopi", scope: !1, file: !1, line: 1, type: !11, scopeLine: 1, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !0, retainedNodes: !14) -!11 = !DISubroutineType(types: !12) -!12 = !{!13, !13} -!13 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) -!14 = !{} -!15 = !DILocalVariable(name: "Param", arg: 1, scope: !10, file: !1, line: 1, type: !13) -!16 = !DILocation(line: 1, column: 38, scope: !10) -!17 = !DILocation(line: 2, column: 3, scope: !10) -!18 = distinct !DISubprogram(name: "bar", linkageName: "_Z3barv", scope: !1, file: !1, line: 5, type: !19, scopeLine: 5, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !0, retainedNodes: !14) -!19 = !DISubroutineType(types: !20) -!20 = !{null} -!21 = !DILocalVariable(name: "End", scope: !18, file: !1, line: 6, type: !13) -!22 = !DILocation(line: 0, scope: !18) -!23 = !DILocalVariable(name: "Index", scope: !18, file: !1, line: 7, type: !13) -!24 = !DILocalVariable(name: "Var", scope: !18, file: !1, line: 8, type: !13) -!25 = !DILocation(line: 9, column: 3, scope: !18) -!26 = !DILocation(line: 9, column: 16, scope: !27) -!27 = distinct !DILexicalBlock(scope: !28, file: !1, line: 9, column: 3) -!28 = distinct !DILexicalBlock(scope: !18, file: !1, line: 9, column: 3) -!29 = !DILocation(line: 9, column: 23, scope: !27) -!30 = !DILocation(line: 9, column: 3, scope: !28) -!31 = distinct !{!31, !30, !32, !33} -!32 = !DILocation(line: 11, column: 13, scope: !28) -!33 = !{!"llvm.loop.mustprogress"} -!34 = !DILocation(line: 12, column: 3, scope: !18) -!35 = !DILocation(line: 13, column: 1, scope: !18) -!36 = distinct !DISubprogram(name: "main", scope: !1, file: !1, line: 15, type: !37, scopeLine: 15, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !0) -!37 = !DISubroutineType(types: !38) -!38 = !{!13} -!39 = !DILocation(line: 16, column: 3, scope: !36) -!40 = !DILocation(line: 17, column: 1, scope: !36) diff --git a/llvm/test/Transforms/IndVarSimplify/pr51735.ll b/llvm/test/Transforms/IndVarSimplify/pr51735.ll deleted file mode 100644 index 3014b3467852..000000000000 --- a/llvm/test/Transforms/IndVarSimplify/pr51735.ll +++ /dev/null @@ -1,104 +0,0 @@ -; RUN: opt -passes="loop(indvars)" \ -; RUN: --experimental-debuginfo-iterators=false -S -o - < %s | \ -; RUN: FileCheck --check-prefix=PRE-CHECK %s -; RUN: opt -passes="loop(indvars,loop-deletion)" \ -; RUN: --experimental-debuginfo-iterators=false -S -o - < %s | \ -; RUN: FileCheck --check-prefix=POST-CHECK %s - -; Make sure that when we delete the loop in the code below, that the variable -; Index has the 777 value. - -; 1 __attribute__((optnone)) int nop() { -; 2 return 0; -; 3 } -; 4 -; 5 void bar() { -; 6 int End = 777; -; 7 int Index = 27; -; 8 char Var = 1; -; 9 for (; Index < End; ++Index) -; 10 ; -; 11 nop(); -; 12 } -; 13 -; 14 int main () { -; 15 bar(); -; 16 } - -; Only the 'indvars' pass is executed. -; As this test case does not fire the 'indvars' transformation, no debug values -; are preserved and or added. - -; PRE-CHECK: for.cond: -; PRE-CHECK: call void @llvm.dbg.value(metadata i32 poison, metadata ![[DBG_1:[0-9]+]], {{.*}} -; PRE-CHECK: call void @llvm.dbg.value(metadata i32 poison, metadata ![[DBG_1]], {{.*}} -; PRE-CHECK: br i1 false, label %for.cond, label %for.end - -; PRE-CHECK: for.end: -; PRE-CHECK-NOT: call void @llvm.dbg.value -; PRE-CHECK: ret void -; PRE-CHECK-DAG: ![[DBG_1]] = !DILocalVariable(name: "Index"{{.*}}) - -; The 'indvars' and 'loop-deletion' passes are executed. -; The loop is deleted and the debug values collected by 'indvars' are used by -; 'loop-deletion' to add the induction variable debug value. - -; POST-CHECK: for.end: -; POST-CHECK: call void @llvm.dbg.value(metadata i32 777, metadata ![[DBG_2:[0-9]+]], {{.*}} -; POST-CHECK: ret void -; POST-CHECK-DAG: ![[DBG_2]] = !DILocalVariable(name: "Index"{{.*}}) - -define dso_local void @_Z3barv() local_unnamed_addr #1 !dbg !15 { -entry: - call void @llvm.dbg.value(metadata i32 777, metadata !19, metadata !DIExpression()), !dbg !20 - call void @llvm.dbg.value(metadata i32 27, metadata !21, metadata !DIExpression()), !dbg !20 - call void @llvm.dbg.value(metadata i32 1, metadata !22, metadata !DIExpression()), !dbg !20 - br label %for.cond, !dbg !23 - -for.cond: ; preds = %for.cond, %entry - %Index.0 = phi i32 [ 27, %entry ], [ %inc, %for.cond ], !dbg !20 - call void @llvm.dbg.value(metadata i32 %Index.0, metadata !21, metadata !DIExpression()), !dbg !20 - %cmp = icmp ult i32 %Index.0, 777, !dbg !24 - %inc = add nuw nsw i32 %Index.0, 1, !dbg !27 - call void @llvm.dbg.value(metadata i32 %inc, metadata !21, metadata !DIExpression()), !dbg !20 - br i1 %cmp, label %for.cond, label %for.end, !dbg !28, !llvm.loop !29 - -for.end: ; preds = %for.cond - ret void, !dbg !33 -} - -declare void @llvm.dbg.value(metadata, metadata, metadata) - -!llvm.dbg.cu = !{!0} -!llvm.module.flags = !{!2, !3, !4, !5, !6, !7, !8} -!llvm.ident = !{!9} - -!0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus_14, file: !1, producer: "clang", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, splitDebugInlining: false, nameTableKind: None) -!1 = !DIFile(filename: "test.cpp", directory: "") -!2 = !{i32 7, !"Dwarf Version", i32 5} -!3 = !{i32 2, !"Debug Info Version", i32 3} -!4 = !{i32 1, !"wchar_size", i32 4} -!5 = !{i32 8, !"PIC Level", i32 2} -!6 = !{i32 7, !"PIE Level", i32 2} -!7 = !{i32 7, !"uwtable", i32 2} -!8 = !{i32 7, !"frame-pointer", i32 2} -!9 = !{!"clang version 18.0.0"} -!13 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) -!15 = distinct !DISubprogram(name: "bar", linkageName: "_Z3barv", scope: !1, file: !1, line: 5, type: !16, scopeLine: 5, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !0, retainedNodes: !18) -!16 = !DISubroutineType(types: !17) -!17 = !{null} -!18 = !{} -!19 = !DILocalVariable(name: "End", scope: !15, file: !1, line: 6, type: !13) -!20 = !DILocation(line: 0, scope: !15) -!21 = !DILocalVariable(name: "Index", scope: !15, file: !1, line: 7, type: !13) -!22 = !DILocalVariable(name: "Var", scope: !15, file: !1, line: 8, type: !13) -!23 = !DILocation(line: 9, column: 3, scope: !15) -!24 = !DILocation(line: 9, column: 16, scope: !25) -!25 = distinct !DILexicalBlock(scope: !26, file: !1, line: 9, column: 3) -!26 = distinct !DILexicalBlock(scope: !15, file: !1, line: 9, column: 3) -!27 = !DILocation(line: 9, column: 23, scope: !25) -!28 = !DILocation(line: 9, column: 3, scope: !26) -!29 = distinct !{!29, !28, !30, !31} -!30 = !DILocation(line: 10, column: 5, scope: !26) -!31 = !{!"llvm.loop.mustprogress"} -!33 = !DILocation(line: 12, column: 1, scope: !15) -- GitLab From 5bd210ace6c165d5093220811ba8d5fc300ac1f9 Mon Sep 17 00:00:00 2001 From: Paul Walker Date: Tue, 21 May 2024 17:11:08 +0000 Subject: [PATCH 103/452] [NFC][LLVM] Autogenerate check lines for some Analysis/LoopAccessAnalysis tests. --- .../LoopAccessAnalysis/depend_diff_types.ll | 56 ++- .../forward-loop-independent.ll | 37 +- .../Analysis/LoopAccessAnalysis/pr64637.ll | 30 +- .../stride-access-dependence.ll | 346 ++++++++++++------ 4 files changed, 317 insertions(+), 152 deletions(-) diff --git a/llvm/test/Analysis/LoopAccessAnalysis/depend_diff_types.ll b/llvm/test/Analysis/LoopAccessAnalysis/depend_diff_types.ll index f333bc3fa231..809b15b20049 100644 --- a/llvm/test/Analysis/LoopAccessAnalysis/depend_diff_types.ll +++ b/llvm/test/Analysis/LoopAccessAnalysis/depend_diff_types.ll @@ -1,3 +1,4 @@ +; NOTE: Assertions have been autogenerated by utils/update_analyze_test_checks.py UTC_ARGS: --version 4 ; RUN: opt -S -disable-output -passes='print' < %s 2>&1 | FileCheck %s @@ -7,7 +8,8 @@ %int_pair = type { i32, i32 } -; CHECK-LABEL: function 'backdep_type_size_equivalence': +define void @backdep_type_size_equivalence(ptr nocapture %vec, i64 %n) { +; CHECK-LABEL: 'backdep_type_size_equivalence' ; CHECK-NEXT: loop: ; CHECK-NEXT: Memory dependences are safe with a maximum safe vector width of 3200 bits ; CHECK-NEXT: Dependences: @@ -23,10 +25,15 @@ ; CHECK-NEXT: store float %val, ptr %gep.iv.min.100, align 8 -> ; CHECK-NEXT: store i32 %indvars.iv.i32, ptr %gep.iv, align 8 ; CHECK-EMPTY: -; CHECK-NEXT: Run-time memory checks: -; CHECK-NEXT: Grouped accesses: - -define void @backdep_type_size_equivalence(ptr nocapture %vec, i64 %n) { +; CHECK-NEXT: Run-time memory checks: +; CHECK-NEXT: Grouped accesses: +; CHECK-EMPTY: +; CHECK-NEXT: Non vectorizable stores to invariant address were not found in loop. +; CHECK-NEXT: SCEV assumptions: +; CHECK-NEXT: {(4 + (8 * %n) + %vec),+,8}<%loop> Added Flags: +; CHECK-EMPTY: +; CHECK-NEXT: Expressions re-written: +; entry: br label %loop @@ -72,20 +79,25 @@ exit: ; different store size than the i32 type, even though their alloc sizes are ; equivalent. This is a negative test to ensure that they are not analyzed as ; in the tests above. -; -; CHECK-LABEL: function 'backdep_type_store_size_equivalence': + +define void @backdep_type_store_size_equivalence(ptr nocapture %vec, i64 %n) { +; CHECK-LABEL: 'backdep_type_store_size_equivalence' ; CHECK-NEXT: loop: -; CHECK-NEXT: Report: unsafe dependent memory operations in loop. -; CHECK-NEXT: Unknown data dependence. +; CHECK-NEXT: Report: unsafe dependent memory operations in loop. Use #pragma clang loop distribute(enable) to allow loop distribution to attempt to isolate the offending operations into a separate loop +; CHECK-NEXT: Unknown data dependence. ; CHECK-NEXT: Dependences: ; CHECK-NEXT: Unknown: ; CHECK-NEXT: %ld.f32 = load float, ptr %gep.iv, align 8 -> ; CHECK-NEXT: store i19 %indvars.iv.i19, ptr %gep.iv, align 8 ; CHECK-EMPTY: -; CHECK-NEXT: Run-time memory checks: -; CHECK-NEXT: Grouped accesses: - -define void @backdep_type_store_size_equivalence(ptr nocapture %vec, i64 %n) { +; CHECK-NEXT: Run-time memory checks: +; CHECK-NEXT: Grouped accesses: +; CHECK-EMPTY: +; CHECK-NEXT: Non vectorizable stores to invariant address were not found in loop. +; CHECK-NEXT: SCEV assumptions: +; CHECK-EMPTY: +; CHECK-NEXT: Expressions re-written: +; entry: br label %loop @@ -114,10 +126,11 @@ exit: ; are done as i64 and i32 types. This is a negative test to ensure that they ; are not analyzed as in the tests above. -; CHECK-LABEL: function 'neg_dist_dep_type_size_equivalence': +define void @neg_dist_dep_type_size_equivalence(ptr nocapture %vec, i64 %n) { +; CHECK-LABEL: 'neg_dist_dep_type_size_equivalence' ; CHECK-NEXT: loop: -; CHECK-NEXT: Report: unsafe dependent memory operations in loop. -; CHECK-NEXT: Backward loop carried data dependence that prevents store-to-load forwarding. +; CHECK-NEXT: Report: unsafe dependent memory operations in loop. Use #pragma clang loop distribute(enable) to allow loop distribution to attempt to isolate the offending operations into a separate loop +; CHECK-NEXT: Backward loop carried data dependence that prevents store-to-load forwarding. ; CHECK-NEXT: Dependences: ; CHECK-NEXT: BackwardVectorizableButPreventsForwarding: ; CHECK-NEXT: %ld.f64 = load double, ptr %gep.iv, align 8 -> @@ -129,12 +142,17 @@ exit: ; CHECK-EMPTY: ; CHECK-NEXT: Unknown: ; CHECK-NEXT: store double %val, ptr %gep.iv.101.i64, align 8 -> -; CHECK-NEXT: store i32 %ld.i64.i32, ptr %gep.iv.n.i64, align 8 +; CHECK-NEXT: store i32 %ld.i64.i32, ptr %gep.iv.n.i64, align 8 ; CHECK-EMPTY: ; CHECK-NEXT: Run-time memory checks: ; CHECK-NEXT: Grouped accesses: - -define void @neg_dist_dep_type_size_equivalence(ptr nocapture %vec, i64 %n) { +; CHECK-EMPTY: +; CHECK-NEXT: Non vectorizable stores to invariant address were not found in loop. +; CHECK-NEXT: SCEV assumptions: +; CHECK-NEXT: {((8 * %n) + %vec),+,8}<%loop> Added Flags: +; CHECK-EMPTY: +; CHECK-NEXT: Expressions re-written: +; entry: br label %loop diff --git a/llvm/test/Analysis/LoopAccessAnalysis/forward-loop-independent.ll b/llvm/test/Analysis/LoopAccessAnalysis/forward-loop-independent.ll index 42d87edd8b4b..f1ae1a897fff 100644 --- a/llvm/test/Analysis/LoopAccessAnalysis/forward-loop-independent.ll +++ b/llvm/test/Analysis/LoopAccessAnalysis/forward-loop-independent.ll @@ -1,3 +1,4 @@ +; NOTE: Assertions have been autogenerated by utils/update_analyze_test_checks.py UTC_ARGS: --version 4 ; RUN: opt -passes='print' -disable-output < %s 2>&1 | FileCheck %s ; Check that loop-indepedent forward dependences are discovered properly. @@ -21,17 +22,31 @@ target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128" define void @f(ptr noalias %A, ptr noalias %B, ptr noalias %C, i64 %N) { - -; CHECK: Dependences: -; CHECK-NEXT: Forward: -; CHECK-NEXT: store i32 %b_p1, ptr %Aidx, align 4 -> -; CHECK-NEXT: %a = load i32, ptr %Aidx, align 4 -; CHECK: ForwardButPreventsForwarding: -; CHECK-NEXT: store i32 %b_p2, ptr %Aidx_next, align 4 -> -; CHECK-NEXT: %a = load i32, ptr %Aidx, align 4 -; CHECK: Forward: -; CHECK-NEXT: store i32 %b_p2, ptr %Aidx_next, align 4 -> -; CHECK-NEXT: store i32 %b_p1, ptr %Aidx, align 4 +; CHECK-LABEL: 'f' +; CHECK-NEXT: for.body: +; CHECK-NEXT: Report: unsafe dependent memory operations in loop. Use #pragma clang loop distribute(enable) to allow loop distribution to attempt to isolate the offending operations into a separate loop +; CHECK-NEXT: Forward loop carried data dependence that prevents store-to-load forwarding. +; CHECK-NEXT: Dependences: +; CHECK-NEXT: Forward: +; CHECK-NEXT: store i32 %b_p1, ptr %Aidx, align 4 -> +; CHECK-NEXT: %a = load i32, ptr %Aidx, align 4 +; CHECK-EMPTY: +; CHECK-NEXT: ForwardButPreventsForwarding: +; CHECK-NEXT: store i32 %b_p2, ptr %Aidx_next, align 4 -> +; CHECK-NEXT: %a = load i32, ptr %Aidx, align 4 +; CHECK-EMPTY: +; CHECK-NEXT: Forward: +; CHECK-NEXT: store i32 %b_p2, ptr %Aidx_next, align 4 -> +; CHECK-NEXT: store i32 %b_p1, ptr %Aidx, align 4 +; CHECK-EMPTY: +; CHECK-NEXT: Run-time memory checks: +; CHECK-NEXT: Grouped accesses: +; CHECK-EMPTY: +; CHECK-NEXT: Non vectorizable stores to invariant address were not found in loop. +; CHECK-NEXT: SCEV assumptions: +; CHECK-EMPTY: +; CHECK-NEXT: Expressions re-written: +; entry: br label %for.body diff --git a/llvm/test/Analysis/LoopAccessAnalysis/pr64637.ll b/llvm/test/Analysis/LoopAccessAnalysis/pr64637.ll index 4d4d2bf3eee8..d3e589cf99cf 100644 --- a/llvm/test/Analysis/LoopAccessAnalysis/pr64637.ll +++ b/llvm/test/Analysis/LoopAccessAnalysis/pr64637.ll @@ -1,4 +1,5 @@ -; RUN: opt -S -passes='print' -pass-remarks-analysis=loop-vectorize -disable-output < %s 2>&1 | FileCheck %s --check-prefix=ANALYSIS +; NOTE: Assertions have been autogenerated by utils/update_analyze_test_checks.py UTC_ARGS: --version 4 +; RUN: opt -S -passes='print' -pass-remarks-analysis=loop-vectorize -disable-output < %s 2>&1 | FileCheck %s ; Test that LoopVectorize don't report 'Use #pragma loop distribute(enable) to allow loop distribution' ; when we already add #pragma clang loop distribute(enable). @@ -17,8 +18,31 @@ ; } define void @foo(ptr noalias nocapture noundef %y, ptr noalias nocapture noundef readnone %x, ptr noalias nocapture noundef readonly %indices, i32 noundef %n) { -; ANALYSIS: Report: unsafe dependent memory operations in loop. -; ANALYSIS: Backward loop carried data dependence that prevents store-to-load forwarding. +; CHECK-LABEL: 'foo' +; CHECK-NEXT: for.body: +; CHECK-NEXT: Report: unsafe dependent memory operations in loop. +; CHECK-NEXT: Backward loop carried data dependence that prevents store-to-load forwarding. +; CHECK-NEXT: Dependences: +; CHECK-NEXT: BackwardVectorizableButPreventsForwarding: +; CHECK-NEXT: %1 = load i32, ptr %arrayidx, align 4 -> +; CHECK-NEXT: store i32 %add8, ptr %arrayidx12, align 4 +; CHECK-EMPTY: +; CHECK-NEXT: BackwardVectorizable: +; CHECK-NEXT: store i32 %add1, ptr %arrayidx, align 4 -> +; CHECK-NEXT: store i32 %add8, ptr %arrayidx12, align 4 +; CHECK-EMPTY: +; CHECK-NEXT: Forward: +; CHECK-NEXT: %1 = load i32, ptr %arrayidx, align 4 -> +; CHECK-NEXT: store i32 %add1, ptr %arrayidx, align 4 +; CHECK-EMPTY: +; CHECK-NEXT: Run-time memory checks: +; CHECK-NEXT: Grouped accesses: +; CHECK-EMPTY: +; CHECK-NEXT: Non vectorizable stores to invariant address were not found in loop. +; CHECK-NEXT: SCEV assumptions: +; CHECK-EMPTY: +; CHECK-NEXT: Expressions re-written: +; entry: %cmp22 = icmp sgt i32 %n, 0 br i1 %cmp22, label %for.body.preheader, label %for.cond.cleanup diff --git a/llvm/test/Analysis/LoopAccessAnalysis/stride-access-dependence.ll b/llvm/test/Analysis/LoopAccessAnalysis/stride-access-dependence.ll index bfdd15f170d0..ef19e173b659 100644 --- a/llvm/test/Analysis/LoopAccessAnalysis/stride-access-dependence.ll +++ b/llvm/test/Analysis/LoopAccessAnalysis/stride-access-dependence.ll @@ -1,3 +1,4 @@ +; NOTE: Assertions have been autogenerated by utils/update_analyze_test_checks.py UTC_ARGS: --version 4 ; RUN: opt -passes='print' -disable-output < %s 2>&1 | FileCheck %s target datalayout = "e-m:e-i64:64-i128:128-n32:64-S128" @@ -10,13 +11,19 @@ target datalayout = "e-m:e-i64:64-i128:128-n32:64-S128" ; B[i] = A[i] + 1; ; } -; CHECK: function 'nodep_Read_Write': -; CHECK-NEXT: for.body: -; CHECK-NEXT: Memory dependences are safe -; CHECK-NEXT: Dependences: -; CHECK-NEXT: Run-time memory checks: - define void @nodep_Read_Write(ptr nocapture %A) { +; CHECK-LABEL: 'nodep_Read_Write' +; CHECK-NEXT: for.body: +; CHECK-NEXT: Memory dependences are safe +; CHECK-NEXT: Dependences: +; CHECK-NEXT: Run-time memory checks: +; CHECK-NEXT: Grouped accesses: +; CHECK-EMPTY: +; CHECK-NEXT: Non vectorizable stores to invariant address were not found in loop. +; CHECK-NEXT: SCEV assumptions: +; CHECK-EMPTY: +; CHECK-NEXT: Expressions re-written: +; entry: %add.ptr = getelementptr inbounds i32, ptr %A, i64 1 br label %for.body @@ -42,17 +49,23 @@ for.body: ; preds = %entry, %for.body ; A[i] = i; ; sum += A[i+3]; ; } -; +; ; return sum; ; } -; CHECK: function 'nodep_Write_Read': -; CHECK-NEXT: for.body: -; CHECK-NEXT: Memory dependences are safe -; CHECK-NEXT: Dependences: -; CHECK-NEXT: Run-time memory checks: - define i32 @nodep_Write_Read(ptr nocapture %A) { +; CHECK-LABEL: 'nodep_Write_Read' +; CHECK-NEXT: for.body: +; CHECK-NEXT: Memory dependences are safe +; CHECK-NEXT: Dependences: +; CHECK-NEXT: Run-time memory checks: +; CHECK-NEXT: Grouped accesses: +; CHECK-EMPTY: +; CHECK-NEXT: Non vectorizable stores to invariant address were not found in loop. +; CHECK-NEXT: SCEV assumptions: +; CHECK-EMPTY: +; CHECK-NEXT: Expressions re-written: +; entry: br label %for.body @@ -81,13 +94,19 @@ for.body: ; preds = %entry, %for.body ; } ; } -; CHECK: function 'nodep_Write_Write': -; CHECK-NEXT: for.body: -; CHECK-NEXT: Memory dependences are safe -; CHECK-NEXT: Dependences: -; CHECK-NEXT: Run-time memory checks: - define void @nodep_Write_Write(ptr nocapture %A) { +; CHECK-LABEL: 'nodep_Write_Write' +; CHECK-NEXT: for.body: +; CHECK-NEXT: Memory dependences are safe +; CHECK-NEXT: Dependences: +; CHECK-NEXT: Run-time memory checks: +; CHECK-NEXT: Grouped accesses: +; CHECK-EMPTY: +; CHECK-NEXT: Non vectorizable stores to invariant address were not found in loop. +; CHECK-NEXT: SCEV assumptions: +; CHECK-EMPTY: +; CHECK-NEXT: Expressions re-written: +; entry: br label %for.body @@ -115,16 +134,24 @@ for.body: ; preds = %entry, %for.body ; A[i+3] = A[i] + 1; ; } -; CHECK: function 'unsafe_Read_Write': -; CHECK-NEXT: for.body: -; CHECK-NEXT: Report: unsafe dependent memory operations in loop -; CHECK-NEXT: Backward loop carried data dependence. -; CHECK-NEXT: Dependences: -; CHECK-NEXT: Backward: -; CHECK-NEXT: %0 = load i32, ptr %arrayidx, align 4 -> -; CHECK-NEXT: store i32 %add, ptr %arrayidx3, align 4 - define void @unsafe_Read_Write(ptr nocapture %A) { +; CHECK-LABEL: 'unsafe_Read_Write' +; CHECK-NEXT: for.body: +; CHECK-NEXT: Report: unsafe dependent memory operations in loop. Use #pragma clang loop distribute(enable) to allow loop distribution to attempt to isolate the offending operations into a separate loop +; CHECK-NEXT: Backward loop carried data dependence. +; CHECK-NEXT: Dependences: +; CHECK-NEXT: Backward: +; CHECK-NEXT: %0 = load i32, ptr %arrayidx, align 4 -> +; CHECK-NEXT: store i32 %add, ptr %arrayidx3, align 4 +; CHECK-EMPTY: +; CHECK-NEXT: Run-time memory checks: +; CHECK-NEXT: Grouped accesses: +; CHECK-EMPTY: +; CHECK-NEXT: Non vectorizable stores to invariant address were not found in loop. +; CHECK-NEXT: SCEV assumptions: +; CHECK-EMPTY: +; CHECK-NEXT: Expressions re-written: +; entry: br label %for.body @@ -155,16 +182,24 @@ for.body: ; preds = %entry, %for.body ; return sum; ; } -; CHECK: function 'unsafe_Write_Read': -; CHECK-NEXT: for.body: -; CHECK-NEXT: Report: unsafe dependent memory operations in loop -; CHECK-NEXT: Backward loop carried data dependence. -; CHECK-NEXT: Dependences: -; CHECK-NEXT: Backward: -; CHECK-NEXT: store i32 %0, ptr %arrayidx, align 4 -> -; CHECK-NEXT: %1 = load i32, ptr %arrayidx2, align 4 - define i32 @unsafe_Write_Read(ptr nocapture %A) { +; CHECK-LABEL: 'unsafe_Write_Read' +; CHECK-NEXT: for.body: +; CHECK-NEXT: Report: unsafe dependent memory operations in loop. Use #pragma clang loop distribute(enable) to allow loop distribution to attempt to isolate the offending operations into a separate loop +; CHECK-NEXT: Backward loop carried data dependence. +; CHECK-NEXT: Dependences: +; CHECK-NEXT: Backward: +; CHECK-NEXT: store i32 %0, ptr %arrayidx, align 4 -> +; CHECK-NEXT: %1 = load i32, ptr %arrayidx2, align 4 +; CHECK-EMPTY: +; CHECK-NEXT: Run-time memory checks: +; CHECK-NEXT: Grouped accesses: +; CHECK-EMPTY: +; CHECK-NEXT: Non vectorizable stores to invariant address were not found in loop. +; CHECK-NEXT: SCEV assumptions: +; CHECK-EMPTY: +; CHECK-NEXT: Expressions re-written: +; entry: br label %for.body @@ -192,16 +227,24 @@ for.body: ; preds = %entry, %for.body ; } ; } -; CHECK: function 'unsafe_Write_Write': -; CHECK-NEXT: for.body: -; CHECK-NEXT: Report: unsafe dependent memory operations in loop -; CHECK-NEXT: Backward loop carried data dependence. -; CHECK-NEXT: Dependences: -; CHECK-NEXT: Backward: -; CHECK-NEXT: store i32 %0, ptr %arrayidx, align 4 -> -; CHECK-NEXT: store i32 %2, ptr %arrayidx3, align 4 - define void @unsafe_Write_Write(ptr nocapture %A) { +; CHECK-LABEL: 'unsafe_Write_Write' +; CHECK-NEXT: for.body: +; CHECK-NEXT: Report: unsafe dependent memory operations in loop. Use #pragma clang loop distribute(enable) to allow loop distribution to attempt to isolate the offending operations into a separate loop +; CHECK-NEXT: Backward loop carried data dependence. +; CHECK-NEXT: Dependences: +; CHECK-NEXT: Backward: +; CHECK-NEXT: store i32 %0, ptr %arrayidx, align 4 -> +; CHECK-NEXT: store i32 %2, ptr %arrayidx3, align 4 +; CHECK-EMPTY: +; CHECK-NEXT: Run-time memory checks: +; CHECK-NEXT: Grouped accesses: +; CHECK-EMPTY: +; CHECK-NEXT: Non vectorizable stores to invariant address were not found in loop. +; CHECK-NEXT: SCEV assumptions: +; CHECK-EMPTY: +; CHECK-NEXT: Expressions re-written: +; entry: br label %for.body @@ -230,15 +273,23 @@ for.body: ; preds = %entry, %for.body ; B[i] = A[i] + 1; ; } -; CHECK: function 'vectorizable_Read_Write': -; CHECK-NEXT: for.body: -; CHECK-NEXT: Memory dependences are safe -; CHECK-NEXT: Dependences: -; CHECK-NEXT: BackwardVectorizable: -; CHECK-NEXT: %0 = load i32, ptr %arrayidx, align 4 -> -; CHECK-NEXT: store i32 %add, ptr %arrayidx2, align 4 - define void @vectorizable_Read_Write(ptr nocapture %A) { +; CHECK-LABEL: 'vectorizable_Read_Write' +; CHECK-NEXT: for.body: +; CHECK-NEXT: Memory dependences are safe with a maximum safe vector width of 64 bits +; CHECK-NEXT: Dependences: +; CHECK-NEXT: BackwardVectorizable: +; CHECK-NEXT: %0 = load i32, ptr %arrayidx, align 4 -> +; CHECK-NEXT: store i32 %add, ptr %arrayidx2, align 4 +; CHECK-EMPTY: +; CHECK-NEXT: Run-time memory checks: +; CHECK-NEXT: Grouped accesses: +; CHECK-EMPTY: +; CHECK-NEXT: Non vectorizable stores to invariant address were not found in loop. +; CHECK-NEXT: SCEV assumptions: +; CHECK-EMPTY: +; CHECK-NEXT: Expressions re-written: +; entry: %add.ptr = getelementptr inbounds i32, ptr %A, i64 4 br label %for.body @@ -265,19 +316,27 @@ for.body: ; preds = %entry, %for.body ; A[i] = i; ; sum += B[i]; ; } -; +; ; return sum; ; } -; CHECK: function 'vectorizable_Write_Read': -; CHECK-NEXT: for.body: -; CHECK-NEXT: Memory dependences are safe -; CHECK-NEXT: Dependences: -; CHECK-NEXT: BackwardVectorizable: -; CHECK-NEXT: store i32 %0, ptr %arrayidx, align 4 -> -; CHECK-NEXT: %1 = load i32, ptr %arrayidx2, align 4 - define i32 @vectorizable_Write_Read(ptr nocapture %A) { +; CHECK-LABEL: 'vectorizable_Write_Read' +; CHECK-NEXT: for.body: +; CHECK-NEXT: Memory dependences are safe with a maximum safe vector width of 64 bits +; CHECK-NEXT: Dependences: +; CHECK-NEXT: BackwardVectorizable: +; CHECK-NEXT: store i32 %0, ptr %arrayidx, align 4 -> +; CHECK-NEXT: %1 = load i32, ptr %arrayidx2, align 4 +; CHECK-EMPTY: +; CHECK-NEXT: Run-time memory checks: +; CHECK-NEXT: Grouped accesses: +; CHECK-EMPTY: +; CHECK-NEXT: Non vectorizable stores to invariant address were not found in loop. +; CHECK-NEXT: SCEV assumptions: +; CHECK-EMPTY: +; CHECK-NEXT: Expressions re-written: +; entry: %add.ptr = getelementptr inbounds i32, ptr %A, i64 4 br label %for.body @@ -307,15 +366,23 @@ for.body: ; preds = %entry, %for.body ; } ; } -; CHECK: function 'vectorizable_Write_Write': -; CHECK-NEXT: for.body: -; CHECK-NEXT: Memory dependences are safe -; CHECK-NEXT: Dependences: -; CHECK-NEXT: BackwardVectorizable: -; CHECK-NEXT: store i32 %0, ptr %arrayidx, align 4 -> -; CHECK-NEXT: store i32 %2, ptr %arrayidx2, align 4 - define void @vectorizable_Write_Write(ptr nocapture %A) { +; CHECK-LABEL: 'vectorizable_Write_Write' +; CHECK-NEXT: for.body: +; CHECK-NEXT: Memory dependences are safe with a maximum safe vector width of 64 bits +; CHECK-NEXT: Dependences: +; CHECK-NEXT: BackwardVectorizable: +; CHECK-NEXT: store i32 %0, ptr %arrayidx, align 4 -> +; CHECK-NEXT: store i32 %2, ptr %arrayidx2, align 4 +; CHECK-EMPTY: +; CHECK-NEXT: Run-time memory checks: +; CHECK-NEXT: Grouped accesses: +; CHECK-EMPTY: +; CHECK-NEXT: Non vectorizable stores to invariant address were not found in loop. +; CHECK-NEXT: SCEV assumptions: +; CHECK-EMPTY: +; CHECK-NEXT: Expressions re-written: +; entry: %add.ptr = getelementptr inbounds i32, ptr %A, i64 4 br label %for.body @@ -346,16 +413,24 @@ for.body: ; preds = %entry, %for.body ; FIXME: This case looks like previous case @vectorizable_Read_Write. It sould ; be vectorizable. -; CHECK: function 'vectorizable_unscaled_Read_Write': -; CHECK-NEXT: for.body: -; CHECK-NEXT: Report: unsafe dependent memory operations in loop -; CHECK-NEXT: Backward loop carried data dependence that prevents store-to-load forwarding. -; CHECK-NEXT: Dependences: -; CHECK-NEXT: BackwardVectorizableButPreventsForwarding: -; CHECK-NEXT: %0 = load i32, ptr %arrayidx, align 4 -> -; CHECK-NEXT: store i32 %add, ptr %arrayidx2, align 4 - define void @vectorizable_unscaled_Read_Write(ptr nocapture %A) { +; CHECK-LABEL: 'vectorizable_unscaled_Read_Write' +; CHECK-NEXT: for.body: +; CHECK-NEXT: Report: unsafe dependent memory operations in loop. Use #pragma clang loop distribute(enable) to allow loop distribution to attempt to isolate the offending operations into a separate loop +; CHECK-NEXT: Backward loop carried data dependence that prevents store-to-load forwarding. +; CHECK-NEXT: Dependences: +; CHECK-NEXT: BackwardVectorizableButPreventsForwarding: +; CHECK-NEXT: %0 = load i32, ptr %arrayidx, align 4 -> +; CHECK-NEXT: store i32 %add, ptr %arrayidx2, align 4 +; CHECK-EMPTY: +; CHECK-NEXT: Run-time memory checks: +; CHECK-NEXT: Grouped accesses: +; CHECK-EMPTY: +; CHECK-NEXT: Non vectorizable stores to invariant address were not found in loop. +; CHECK-NEXT: SCEV assumptions: +; CHECK-EMPTY: +; CHECK-NEXT: Expressions re-written: +; entry: %add.ptr = getelementptr inbounds i8, ptr %A, i64 14 br label %for.body @@ -382,19 +457,27 @@ for.body: ; preds = %entry, %for.body ; A[i] = i; ; sum += B[i]; ; } -; +; ; return sum; ; } -; CHECK: function 'vectorizable_unscaled_Write_Read': -; CHECK-NEXT: for.body: -; CHECK-NEXT: Memory dependences are safe -; CHECK-NEXT: Dependences: -; CHECK-NEXT: BackwardVectorizable: -; CHECK-NEXT: store i32 %0, ptr %arrayidx, align 4 -> -; CHECK-NEXT: %1 = load i32, ptr %arrayidx2, align 4 - define i32 @vectorizable_unscaled_Write_Read(ptr nocapture %A) { +; CHECK-LABEL: 'vectorizable_unscaled_Write_Read' +; CHECK-NEXT: for.body: +; CHECK-NEXT: Memory dependences are safe with a maximum safe vector width of 64 bits +; CHECK-NEXT: Dependences: +; CHECK-NEXT: BackwardVectorizable: +; CHECK-NEXT: store i32 %0, ptr %arrayidx, align 4 -> +; CHECK-NEXT: %1 = load i32, ptr %arrayidx2, align 4 +; CHECK-EMPTY: +; CHECK-NEXT: Run-time memory checks: +; CHECK-NEXT: Grouped accesses: +; CHECK-EMPTY: +; CHECK-NEXT: Non vectorizable stores to invariant address were not found in loop. +; CHECK-NEXT: SCEV assumptions: +; CHECK-EMPTY: +; CHECK-NEXT: Expressions re-written: +; entry: %add.ptr = getelementptr inbounds i8, ptr %A, i64 17 br label %for.body @@ -422,16 +505,24 @@ for.body: ; preds = %entry, %for.body ; B[i] = A[i] + 1; ; } -; CHECK: function 'unsafe_unscaled_Read_Write': -; CHECK-NEXT: for.body: -; CHECK-NEXT: Report: unsafe dependent memory operations in loop -; CHECK-NEXT: Backward loop carried data dependence. -; CHECK-NEXT: Dependences: -; CHECK-NEXT: Backward: -; CHECK-NEXT: %0 = load i32, ptr %arrayidx, align 4 -> -; CHECK-NEXT: store i32 %add, ptr %arrayidx2, align 4 - define void @unsafe_unscaled_Read_Write(ptr nocapture %A) { +; CHECK-LABEL: 'unsafe_unscaled_Read_Write' +; CHECK-NEXT: for.body: +; CHECK-NEXT: Report: unsafe dependent memory operations in loop. Use #pragma clang loop distribute(enable) to allow loop distribution to attempt to isolate the offending operations into a separate loop +; CHECK-NEXT: Backward loop carried data dependence. +; CHECK-NEXT: Dependences: +; CHECK-NEXT: Backward: +; CHECK-NEXT: %0 = load i32, ptr %arrayidx, align 4 -> +; CHECK-NEXT: store i32 %add, ptr %arrayidx2, align 4 +; CHECK-EMPTY: +; CHECK-NEXT: Run-time memory checks: +; CHECK-NEXT: Grouped accesses: +; CHECK-EMPTY: +; CHECK-NEXT: Non vectorizable stores to invariant address were not found in loop. +; CHECK-NEXT: SCEV assumptions: +; CHECK-EMPTY: +; CHECK-NEXT: Expressions re-written: +; entry: %add.ptr = getelementptr inbounds i8, ptr %A, i64 11 br label %for.body @@ -451,15 +542,6 @@ for.body: ; preds = %entry, %for.body br i1 %cmp, label %for.body, label %for.cond.cleanup } -; CHECK: function 'unsafe_unscaled_Read_Write2': -; CHECK-NEXT: for.body: -; CHECK-NEXT: Report: unsafe dependent memory operations in loop -; CHECK-NEXT: Backward loop carried data dependence. -; CHECK-NEXT: Dependences: -; CHECK-NEXT: Backward: -; CHECK-NEXT: %0 = load i32, ptr %arrayidx, align 4 -> -; CHECK-NEXT: store i32 %add, ptr %arrayidx2, align 4 - ; void unsafe_unscaled_Read_Write2(int *A) { ; int *B = (int *)((char *)A + 1); ; for (unsigned i = 0; i < 1024; i+=2) @@ -467,6 +549,23 @@ for.body: ; preds = %entry, %for.body ; } define void @unsafe_unscaled_Read_Write2(ptr nocapture %A) { +; CHECK-LABEL: 'unsafe_unscaled_Read_Write2' +; CHECK-NEXT: for.body: +; CHECK-NEXT: Report: unsafe dependent memory operations in loop. Use #pragma clang loop distribute(enable) to allow loop distribution to attempt to isolate the offending operations into a separate loop +; CHECK-NEXT: Backward loop carried data dependence. +; CHECK-NEXT: Dependences: +; CHECK-NEXT: Backward: +; CHECK-NEXT: %0 = load i32, ptr %arrayidx, align 4 -> +; CHECK-NEXT: store i32 %add, ptr %arrayidx2, align 4 +; CHECK-EMPTY: +; CHECK-NEXT: Run-time memory checks: +; CHECK-NEXT: Grouped accesses: +; CHECK-EMPTY: +; CHECK-NEXT: Non vectorizable stores to invariant address were not found in loop. +; CHECK-NEXT: SCEV assumptions: +; CHECK-EMPTY: +; CHECK-NEXT: Expressions re-written: +; entry: %add.ptr = getelementptr inbounds i8, ptr %A, i64 1 br label %for.body @@ -500,19 +599,28 @@ for.body: ; preds = %entry, %for.body ; ; The access (2) has overlaps with (1) and (3). -; CHECK: function 'interleaved_stores': -; CHECK-NEXT: for.body: -; CHECK-NEXT: Report: unsafe dependent memory operations in loop -; CHECK-NEXT: Backward loop carried data dependence. -; CHECK-NEXT: Dependences: -; CHECK-NEXT: Backward: -; CHECK-NEXT: store i32 %2, ptr %arrayidx5, align 4 -> -; CHECK-NEXT: store i32 %2, ptr %arrayidx9, align 4 -; CHECK: Backward: -; CHECK-NEXT: store i32 %0, ptr %arrayidx2, align 4 -> -; CHECK-NEXT: store i32 %2, ptr %arrayidx5, align 4 - define void @interleaved_stores(ptr nocapture %A) { +; CHECK-LABEL: 'interleaved_stores' +; CHECK-NEXT: for.body: +; CHECK-NEXT: Report: unsafe dependent memory operations in loop. Use #pragma clang loop distribute(enable) to allow loop distribution to attempt to isolate the offending operations into a separate loop +; CHECK-NEXT: Backward loop carried data dependence. +; CHECK-NEXT: Dependences: +; CHECK-NEXT: Backward: +; CHECK-NEXT: store i32 %2, ptr %arrayidx5, align 4 -> +; CHECK-NEXT: store i32 %2, ptr %arrayidx9, align 4 +; CHECK-EMPTY: +; CHECK-NEXT: Backward: +; CHECK-NEXT: store i32 %0, ptr %arrayidx2, align 4 -> +; CHECK-NEXT: store i32 %2, ptr %arrayidx5, align 4 +; CHECK-EMPTY: +; CHECK-NEXT: Run-time memory checks: +; CHECK-NEXT: Grouped accesses: +; CHECK-EMPTY: +; CHECK-NEXT: Non vectorizable stores to invariant address were not found in loop. +; CHECK-NEXT: SCEV assumptions: +; CHECK-EMPTY: +; CHECK-NEXT: Expressions re-written: +; entry: %incdec.ptr = getelementptr inbounds i8, ptr %A, i64 1 br label %for.body -- GitLab From 9051fc706fd5f4517fa880e6cb7a1ba9e4c0483d Mon Sep 17 00:00:00 2001 From: Paul Walker Date: Tue, 21 May 2024 17:24:43 +0000 Subject: [PATCH 104/452] [NFC][LLVM] Fix typos in llvm/test/MC/AArch64/SVE --- .../{condtion-codes.s => condition-codes.s} | 0 llvm/test/MC/AArch64/SVE/sqdecd-diagnostics.s | 4 +-- llvm/test/MC/AArch64/SVE/sqincp-diagnostics.s | 32 +++++++++---------- 3 files changed, 18 insertions(+), 18 deletions(-) rename llvm/test/MC/AArch64/SVE/{condtion-codes.s => condition-codes.s} (100%) diff --git a/llvm/test/MC/AArch64/SVE/condtion-codes.s b/llvm/test/MC/AArch64/SVE/condition-codes.s similarity index 100% rename from llvm/test/MC/AArch64/SVE/condtion-codes.s rename to llvm/test/MC/AArch64/SVE/condition-codes.s diff --git a/llvm/test/MC/AArch64/SVE/sqdecd-diagnostics.s b/llvm/test/MC/AArch64/SVE/sqdecd-diagnostics.s index 658af848c363..96b14b9ec112 100644 --- a/llvm/test/MC/AArch64/SVE/sqdecd-diagnostics.s +++ b/llvm/test/MC/AArch64/SVE/sqdecd-diagnostics.s @@ -18,9 +18,9 @@ sqdecd sp // CHECK-NEXT: sqdecd sp // CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: -uqdecd z0.s +sqdecd z0.s // CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width -// CHECK-NEXT: uqdecd z0.s +// CHECK-NEXT: sqdecd z0.s // CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: diff --git a/llvm/test/MC/AArch64/SVE/sqincp-diagnostics.s b/llvm/test/MC/AArch64/SVE/sqincp-diagnostics.s index 2dfd49584908..862af7c9203b 100644 --- a/llvm/test/MC/AArch64/SVE/sqincp-diagnostics.s +++ b/llvm/test/MC/AArch64/SVE/sqincp-diagnostics.s @@ -3,48 +3,48 @@ // ------------------------------------------------------------------------- // // Invalid result register -uqdecp sp, p0 +sqincp sp, p0 // CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid operand -// CHECK-NEXT: uqdecp sp, p0 +// CHECK-NEXT: sqincp sp, p0 // CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: -uqdecp z0.b, p0 +sqincp z0.b, p0 // CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width -// CHECK-NEXT: uqdecp z0.b, p0 +// CHECK-NEXT: sqincp z0.b, p0 // CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: -uqdecp x0, p0.b, w0 +sqincp w0, p0.b, w0 // CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid operand -// CHECK-NEXT: uqdecp x0, p0.b, w0 +// CHECK-NEXT: sqincp w0, p0.b, w0 // CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: -uqdecp x0, p0.b, x1 +sqincp x0, p0.b, x1 // CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid operand -// CHECK-NEXT: uqdecp x0, p0.b, x1 +// CHECK-NEXT: sqincp x0, p0.b, x1 // CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: // ------------------------------------------------------------------------- // // Invalid predicate operand -uqdecp x0, p0 +sqincp x0, p0 // CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid predicate register -// CHECK-NEXT: uqdecp x0, p0 +// CHECK-NEXT: sqincp x0, p0 // CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: -uqdecp x0, p0/z +sqincp x0, p0/z // CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid predicate register -// CHECK-NEXT: uqdecp x0, p0/z +// CHECK-NEXT: sqincp x0, p0/z // CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: -uqdecp x0, p0/m +sqincp x0, p0/m // CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid predicate register -// CHECK-NEXT: uqdecp x0, p0/m +// CHECK-NEXT: sqincp x0, p0/m // CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: -uqdecp x0, p0.q +sqincp x0, p0.q // CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid predicate register -// CHECK-NEXT: uqdecp x0, p0.q +// CHECK-NEXT: sqincp x0, p0.q // CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: sqincp z0.d, p0.b -- GitLab From 25c021a8638d203022128edb1be9000134bfe24f Mon Sep 17 00:00:00 2001 From: Paul Walker Date: Tue, 21 May 2024 17:34:30 +0000 Subject: [PATCH 105/452] [NFC] Fix typo in llvm/test/Transforms/Util/add-TLI-mappings.ll --- llvm/test/Transforms/Util/add-TLI-mappings.ll | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/llvm/test/Transforms/Util/add-TLI-mappings.ll b/llvm/test/Transforms/Util/add-TLI-mappings.ll index 0e005ae75ef5..4e4b81e89a32 100644 --- a/llvm/test/Transforms/Util/add-TLI-mappings.ll +++ b/llvm/test/Transforms/Util/add-TLI-mappings.ll @@ -274,19 +274,19 @@ attributes #0 = { nounwind readnone } ; ARMPL-SAME: _ZGVsMxvl4_modff(armpl_svmodf_f32_x)" } ; ARMPL: attributes #[[SIN]] = { "vector-function-abi-variant"= ; ARMPL-SAME: "_ZGV_LLVM_N2v_sin(armpl_vsinq_f64), -; ARMPL-SAME _ZGVsMxv_sin(armpl_svsin_f64_x)" } +; ARMPL-SAME: _ZGVsMxv_sin(armpl_svsin_f64_x)" } ; ARMPL: attributes #[[SINCOS]] = { "vector-function-abi-variant"= ; ARMPL-SAME: "_ZGV_LLVM_N2vl8l8_sincos(armpl_vsincosq_f64), -; ARMPL-SAME: _ZGVsMxvl8l8_sincos(armpl_svsincos_f64_x)" } +; ARMPL-SAME: _ZGVsMxvl8l8_sincos(armpl_svsincos_f64_x)" } ; ARMPL: attributes #[[SINCOSF]] = { "vector-function-abi-variant"= ; ARMPL-SAME: "_ZGV_LLVM_N4vl4l4_sincosf(armpl_vsincosq_f32), ; ARMPL-SAME: _ZGVsMxvl4l4_sincosf(armpl_svsincos_f32_x)" } ; ARMPL: attributes #[[SINCOSPI]] = { "vector-function-abi-variant"= ; ARMPL-SAME: "_ZGV_LLVM_N2vl8l8_sincospi(armpl_vsincospiq_f64), -; ARMPL-SAME: _ZGVsMxvl8l8_sincospi(armpl_svsincospi_f64_x)" } +; ARMPL-SAME: _ZGVsMxvl8l8_sincospi(armpl_svsincospi_f64_x)" } ; ARMPL: attributes #[[SINCOSPIF]] = { "vector-function-abi-variant"= ; ARMPL-SAME: "_ZGV_LLVM_N4vl4l4_sincospif(armpl_vsincospiq_f32), ; ARMPL-SAME: _ZGVsMxvl4l4_sincospif(armpl_svsincospi_f32_x)" } ; ARMPL: attributes #[[LOG10]] = { "vector-function-abi-variant"= ; ARMPL-SAME: "_ZGV_LLVM_N4v_llvm.log10.f32(armpl_vlog10q_f32), -; ARMPL-SAME _ZGVsMxv_llvm.log10.f32(armpl_svlog10_f32_x)" } +; ARMPL-SAME: _ZGVsMxv_llvm.log10.f32(armpl_svlog10_f32_x)" } -- GitLab From c912f0e773386cc309155b78e2441ee5f1052c13 Mon Sep 17 00:00:00 2001 From: pranavm-nvidia <49246958+pranavm-nvidia@users.noreply.github.com> Date: Wed, 22 May 2024 03:44:22 -0700 Subject: [PATCH 106/452] [mlir][python] Add bindings for mlirDenseElementsAttrGet (#91389) This change adds bindings for `mlirDenseElementsAttrGet` which accepts a list of MLIR attributes and constructs a DenseElementsAttr. This allows for creating `DenseElementsAttr`s of types not natively supported by Python (e.g. BF16) without requiring other dependencies (e.g. `numpy` + `ml-dtypes`). --- mlir/lib/Bindings/Python/IRAttributes.cpp | 77 +++++++++++++++++++++ mlir/test/python/ir/array_attributes.py | 82 +++++++++++++++++++++++ 2 files changed, 159 insertions(+) diff --git a/mlir/lib/Bindings/Python/IRAttributes.cpp b/mlir/lib/Bindings/Python/IRAttributes.cpp index dda2003ba037..b5f31aa5dec5 100644 --- a/mlir/lib/Bindings/Python/IRAttributes.cpp +++ b/mlir/lib/Bindings/Python/IRAttributes.cpp @@ -15,6 +15,7 @@ #include "PybindUtils.h" #include "llvm/ADT/ScopeExit.h" +#include "llvm/Support/raw_ostream.h" #include "mlir-c/BuiltinAttributes.h" #include "mlir-c/BuiltinTypes.h" @@ -72,6 +73,27 @@ Raises: type or if the buffer does not meet expectations. )"; +static const char kDenseElementsAttrGetFromListDocstring[] = + R"(Gets a DenseElementsAttr from a Python list of attributes. + +Note that it can be expensive to construct attributes individually. +For a large number of elements, consider using a Python buffer or array instead. + +Args: + attrs: A list of attributes. + type: The desired shape and type of the resulting DenseElementsAttr. + If not provided, the element type is determined based on the type + of the 0th attribute and the shape is `[len(attrs)]`. + context: Explicit context, if not from context manager. + +Returns: + DenseElementsAttr on success. + +Raises: + ValueError: If the type of the attributes does not match the type + specified by `shaped_type`. +)"; + static const char kDenseResourceElementsAttrGetFromBufferDocstring[] = R"(Gets a DenseResourceElementsAttr from a Python buffer or array. @@ -647,6 +669,57 @@ public: static constexpr const char *pyClassName = "DenseElementsAttr"; using PyConcreteAttribute::PyConcreteAttribute; + static PyDenseElementsAttribute + getFromList(py::list attributes, std::optional explicitType, + DefaultingPyMlirContext contextWrapper) { + + const size_t numAttributes = py::len(attributes); + if (numAttributes == 0) + throw py::value_error("Attributes list must be non-empty."); + + MlirType shapedType; + if (explicitType) { + if ((!mlirTypeIsAShaped(*explicitType) || + !mlirShapedTypeHasStaticShape(*explicitType))) { + + std::string message; + llvm::raw_string_ostream os(message); + os << "Expected a static ShapedType for the shaped_type parameter: " + << py::repr(py::cast(*explicitType)); + throw py::value_error(os.str()); + } + shapedType = *explicitType; + } else { + SmallVector shape{static_cast(numAttributes)}; + shapedType = mlirRankedTensorTypeGet( + shape.size(), shape.data(), + mlirAttributeGetType(pyTryCast(attributes[0])), + mlirAttributeGetNull()); + } + + SmallVector mlirAttributes; + mlirAttributes.reserve(numAttributes); + for (const py::handle &attribute : attributes) { + MlirAttribute mlirAttribute = pyTryCast(attribute); + MlirType attrType = mlirAttributeGetType(mlirAttribute); + mlirAttributes.push_back(mlirAttribute); + + if (!mlirTypeEqual(mlirShapedTypeGetElementType(shapedType), attrType)) { + std::string message; + llvm::raw_string_ostream os(message); + os << "All attributes must be of the same type and match " + << "the type parameter: expected=" << py::repr(py::cast(shapedType)) + << ", but got=" << py::repr(py::cast(attrType)); + throw py::value_error(os.str()); + } + } + + MlirAttribute elements = mlirDenseElementsAttrGet( + shapedType, mlirAttributes.size(), mlirAttributes.data()); + + return PyDenseElementsAttribute(contextWrapper->getRef(), elements); + } + static PyDenseElementsAttribute getFromBuffer(py::buffer array, bool signless, std::optional explicitType, @@ -883,6 +956,10 @@ public: py::arg("type") = py::none(), py::arg("shape") = py::none(), py::arg("context") = py::none(), kDenseElementsAttrGetDocstring) + .def_static("get", PyDenseElementsAttribute::getFromList, + py::arg("attrs"), py::arg("type") = py::none(), + py::arg("context") = py::none(), + kDenseElementsAttrGetFromListDocstring) .def_static("get_splat", PyDenseElementsAttribute::getSplat, py::arg("shaped_type"), py::arg("element_attr"), "Gets a DenseElementsAttr where all values are the same") diff --git a/mlir/test/python/ir/array_attributes.py b/mlir/test/python/ir/array_attributes.py index 9251588a4c48..2bc403aace83 100644 --- a/mlir/test/python/ir/array_attributes.py +++ b/mlir/test/python/ir/array_attributes.py @@ -50,6 +50,87 @@ def testGetDenseElementsUnSupportedTypeOkIfExplicitTypeProvided(): print(np.array(attr)) +################################################################################ +# Tests of the list of attributes .get() factory method +################################################################################ + + +# CHECK-LABEL: TEST: testGetDenseElementsFromList +@run +def testGetDenseElementsFromList(): + with Context(), Location.unknown(): + attrs = [FloatAttr.get(F64Type.get(), 1.0), FloatAttr.get(F64Type.get(), 2.0)] + attr = DenseElementsAttr.get(attrs) + + # CHECK: dense<[1.000000e+00, 2.000000e+00]> : tensor<2xf64> + print(attr) + + +# CHECK-LABEL: TEST: testGetDenseElementsFromListWithExplicitType +@run +def testGetDenseElementsFromListWithExplicitType(): + with Context(), Location.unknown(): + attrs = [FloatAttr.get(F64Type.get(), 1.0), FloatAttr.get(F64Type.get(), 2.0)] + shaped_type = ShapedType(Type.parse("tensor<2xf64>")) + attr = DenseElementsAttr.get(attrs, shaped_type) + + # CHECK: dense<[1.000000e+00, 2.000000e+00]> : tensor<2xf64> + print(attr) + + +# CHECK-LABEL: TEST: testGetDenseElementsFromListEmptyList +@run +def testGetDenseElementsFromListEmptyList(): + with Context(), Location.unknown(): + attrs = [] + + try: + attr = DenseElementsAttr.get(attrs) + except ValueError as e: + # CHECK: Attributes list must be non-empty + print(e) + + +# CHECK-LABEL: TEST: testGetDenseElementsFromListNonAttributeType +@run +def testGetDenseElementsFromListNonAttributeType(): + with Context(), Location.unknown(): + attrs = [1.0] + + try: + attr = DenseElementsAttr.get(attrs) + except RuntimeError as e: + # CHECK: Invalid attribute when attempting to create an ArrayAttribute + print(e) + + +# CHECK-LABEL: TEST: testGetDenseElementsFromListMismatchedType +@run +def testGetDenseElementsFromListMismatchedType(): + with Context(), Location.unknown(): + attrs = [FloatAttr.get(F64Type.get(), 1.0), FloatAttr.get(F64Type.get(), 2.0)] + shaped_type = ShapedType(Type.parse("tensor<2xf32>")) + + try: + attr = DenseElementsAttr.get(attrs, shaped_type) + except ValueError as e: + # CHECK: All attributes must be of the same type and match the type parameter + print(e) + + +# CHECK-LABEL: TEST: testGetDenseElementsFromListMixedTypes +@run +def testGetDenseElementsFromListMixedTypes(): + with Context(), Location.unknown(): + attrs = [FloatAttr.get(F64Type.get(), 1.0), FloatAttr.get(F32Type.get(), 2.0)] + + try: + attr = DenseElementsAttr.get(attrs) + except ValueError as e: + # CHECK: All attributes must be of the same type and match the type parameter + print(e) + + ################################################################################ # Splats. ################################################################################ @@ -205,6 +286,7 @@ def testGetDenseElementsBoolSplat(): ### float and double arrays. + # CHECK-LABEL: TEST: testGetDenseElementsF16 @run def testGetDenseElementsF16(): -- GitLab From 9604e5ce8b5607cd88ba130314fc7ae8545542e1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timm=20B=C3=A4der?= Date: Tue, 21 May 2024 12:59:03 +0200 Subject: [PATCH 107/452] [clang][Interp] Allow stepping back from a one-past-the-end pointer ... back into range of the array. --- clang/lib/AST/Interp/Interp.h | 6 +++++- clang/lib/AST/Interp/Pointer.h | 3 --- clang/test/AST/Interp/arrays.cpp | 4 ++++ 3 files changed, 9 insertions(+), 4 deletions(-) diff --git a/clang/lib/AST/Interp/Interp.h b/clang/lib/AST/Interp/Interp.h index c5607169b25f..7ef963c810c8 100644 --- a/clang/lib/AST/Interp/Interp.h +++ b/clang/lib/AST/Interp/Interp.h @@ -1555,8 +1555,12 @@ bool OffsetHelper(InterpState &S, CodePtr OpPC, const T &Offset, if (!CheckArray(S, OpPC, Ptr)) return false; - uint64_t Index = Ptr.getIndex(); uint64_t MaxIndex = static_cast(Ptr.getNumElems()); + uint64_t Index; + if (Ptr.isOnePastEnd()) + Index = MaxIndex; + else + Index = Ptr.getIndex(); bool Invalid = false; // Helper to report an invalid offset, computed as APSInt. diff --git a/clang/lib/AST/Interp/Pointer.h b/clang/lib/AST/Interp/Pointer.h index 9468bdbf00cc..93ca754d04a6 100644 --- a/clang/lib/AST/Interp/Pointer.h +++ b/clang/lib/AST/Interp/Pointer.h @@ -537,9 +537,6 @@ public: if (isZero()) return 0; - if (isElementPastEnd()) - return 1; - // narrow()ed element in a composite array. if (asBlockPointer().Base > sizeof(InlineDescriptor) && asBlockPointer().Base == Offset) diff --git a/clang/test/AST/Interp/arrays.cpp b/clang/test/AST/Interp/arrays.cpp index e936ec6dc894..dd5064d993e6 100644 --- a/clang/test/AST/Interp/arrays.cpp +++ b/clang/test/AST/Interp/arrays.cpp @@ -54,6 +54,10 @@ constexpr int derefPtr(const int *d) { } static_assert(derefPtr(data) == 5, ""); +/// Make sure we can refer to the one-past-the-end element +/// and then return back to the end of the array. +static_assert((&data[5])[-1] == 1, ""); + constexpr int storePtr() { int b[] = {1,2,3,4}; int *c = b; -- GitLab From 8619054fb76ad0ceb9c3b1c90e643bd469daecf8 Mon Sep 17 00:00:00 2001 From: LLVM GN Syncbot Date: Wed, 22 May 2024 10:46:51 +0000 Subject: [PATCH 108/452] [gn build] Port 11b97da83141 --- .../gn/secondary/clang/lib/StaticAnalyzer/Checkers/BUILD.gn | 1 + 1 file changed, 1 insertion(+) diff --git a/llvm/utils/gn/secondary/clang/lib/StaticAnalyzer/Checkers/BUILD.gn b/llvm/utils/gn/secondary/clang/lib/StaticAnalyzer/Checkers/BUILD.gn index da48149c4d90..333d74e5c720 100644 --- a/llvm/utils/gn/secondary/clang/lib/StaticAnalyzer/Checkers/BUILD.gn +++ b/llvm/utils/gn/secondary/clang/lib/StaticAnalyzer/Checkers/BUILD.gn @@ -111,6 +111,7 @@ static_library("Checkers") { "ReturnValueChecker.cpp", "RunLoopAutoreleaseLeakChecker.cpp", "STLAlgorithmModeling.cpp", + "SetgidSetuidOrderChecker.cpp", "SimpleStreamChecker.cpp", "SmartPtrChecker.cpp", "SmartPtrModeling.cpp", -- GitLab From bbc4c2e047107c62d49ce1e0474635ea55a2b006 Mon Sep 17 00:00:00 2001 From: Simon Pilgrim Date: Wed, 22 May 2024 11:53:59 +0100 Subject: [PATCH 109/452] [DAG] SimplifyDemandedBits - ensure we have simplified the shift operands before folding to AVG Pulled out of #92096 - ensure we have completed a topological simplification of the SRA/SRL shift operands before we try to combine to a AVG node, as its difficult to later simplify through AVG nodes. --- .../CodeGen/SelectionDAG/TargetLowering.cpp | 22 ++++++++++--------- llvm/test/CodeGen/AArch64/arm64-vhadd.ll | 2 +- 2 files changed, 13 insertions(+), 11 deletions(-) diff --git a/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp b/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp index 3ec6b9b79507..b6d4050236b7 100644 --- a/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp @@ -1908,11 +1908,6 @@ bool TargetLowering::SimplifyDemandedBits( SDValue Op1 = Op.getOperand(1); EVT ShiftVT = Op1.getValueType(); - // Try to match AVG patterns. - if (SDValue AVG = combineShiftToAVG(Op, TLO.DAG, *this, DemandedBits, - DemandedElts, Depth + 1)) - return TLO.CombineTo(Op, AVG); - KnownBits KnownSA = TLO.DAG.computeKnownBits(Op1, DemandedElts, Depth + 1); if (KnownSA.isConstant() && KnownSA.getConstant().ult(BitWidth)) { unsigned ShAmt = KnownSA.getConstant().getZExtValue(); @@ -1994,6 +1989,12 @@ bool TargetLowering::SimplifyDemandedBits( // shift amounts. Known = TLO.DAG.computeKnownBits(Op, DemandedElts, Depth); } + + // Try to match AVG patterns (after shift simplification). + if (SDValue AVG = combineShiftToAVG(Op, TLO.DAG, *this, DemandedBits, + DemandedElts, Depth + 1)) + return TLO.CombineTo(Op, AVG); + break; } case ISD::SRA: { @@ -2015,11 +2016,6 @@ bool TargetLowering::SimplifyDemandedBits( if (DemandedBits.isOne()) return TLO.CombineTo(Op, TLO.DAG.getNode(ISD::SRL, dl, VT, Op0, Op1)); - // Try to match AVG patterns. - if (SDValue AVG = combineShiftToAVG(Op, TLO.DAG, *this, DemandedBits, - DemandedElts, Depth + 1)) - return TLO.CombineTo(Op, AVG); - KnownBits KnownSA = TLO.DAG.computeKnownBits(Op1, DemandedElts, Depth + 1); if (KnownSA.isConstant() && KnownSA.getConstant().ult(BitWidth)) { unsigned ShAmt = KnownSA.getConstant().getZExtValue(); @@ -2106,6 +2102,12 @@ bool TargetLowering::SimplifyDemandedBits( } } } + + // Try to match AVG patterns (after shift simplification). + if (SDValue AVG = combineShiftToAVG(Op, TLO.DAG, *this, DemandedBits, + DemandedElts, Depth + 1)) + return TLO.CombineTo(Op, AVG); + break; } case ISD::FSHL: diff --git a/llvm/test/CodeGen/AArch64/arm64-vhadd.ll b/llvm/test/CodeGen/AArch64/arm64-vhadd.ll index e754f01daa2a..a8be8bbd193a 100644 --- a/llvm/test/CodeGen/AArch64/arm64-vhadd.ll +++ b/llvm/test/CodeGen/AArch64/arm64-vhadd.ll @@ -1379,7 +1379,7 @@ define <8 x i8> @sextmask2v8i8(<8 x i16> %src1, <8 x i8> %src2) { define <8 x i8> @sextmask3v8i8(<8 x i16> %src1, <8 x i8> %src2) { ; CHECK-LABEL: sextmask3v8i8: ; CHECK: // %bb.0: -; CHECK-NEXT: sshr.8h v0, v0, #7 +; CHECK-NEXT: ushr.8h v0, v0, #7 ; CHECK-NEXT: sshll.8h v1, v1, #0 ; CHECK-NEXT: shadd.8h v0, v0, v1 ; CHECK-NEXT: xtn.8b v0, v0 -- GitLab From f68548135b8f9a02beac842646ab89bcaad9d400 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timm=20B=C3=A4der?= Date: Tue, 21 May 2024 13:46:19 +0200 Subject: [PATCH 110/452] [clang][Interp] Fix checking unions for initialization --- clang/lib/AST/Interp/EvaluationResult.cpp | 4 ++++ clang/test/AST/Interp/unions.cpp | 14 ++++++++++++++ 2 files changed, 18 insertions(+) create mode 100644 clang/test/AST/Interp/unions.cpp diff --git a/clang/lib/AST/Interp/EvaluationResult.cpp b/clang/lib/AST/Interp/EvaluationResult.cpp index e92d686c724c..79f222ce2b30 100644 --- a/clang/lib/AST/Interp/EvaluationResult.cpp +++ b/clang/lib/AST/Interp/EvaluationResult.cpp @@ -115,6 +115,10 @@ static bool CheckFieldsInitialized(InterpState &S, SourceLocation Loc, DiagnoseUninitializedSubobject(S, Loc, F.Decl); Result = false; } + + // Only the first member of a union needs to be initialized. + if (R->isUnion()) + break; } // Check Fields in all bases diff --git a/clang/test/AST/Interp/unions.cpp b/clang/test/AST/Interp/unions.cpp new file mode 100644 index 000000000000..08ca39c3cb08 --- /dev/null +++ b/clang/test/AST/Interp/unions.cpp @@ -0,0 +1,14 @@ +// RUN: %clang_cc1 -fexperimental-new-constant-interpreter -verify=expected,both %s +// RUN: %clang_cc1 -verify=ref,both %s + +// both-no-diagnostics + +union U { + int a; + int b; +}; + +constexpr U a = {12}; +static_assert(a.a == 12, ""); + + -- GitLab From ba0e871db81d8527382a051a0abf1ce2a171d8bf Mon Sep 17 00:00:00 2001 From: Florian Hahn Date: Wed, 22 May 2024 13:11:01 +0100 Subject: [PATCH 111/452] [ConstraintElim] Look through SExt with precond Op sge 0. Look through SExt with a precondition that the operand is signed positive. https://alive2.llvm.org/ce/z/zvVVHj --- llvm/lib/Transforms/Scalar/ConstraintElimination.cpp | 6 ++++++ .../ConstraintElimination/sext-unsigned-predicates.ll | 6 +++--- .../transfer-signed-facts-to-unsigned.ll | 6 ++---- 3 files changed, 11 insertions(+), 7 deletions(-) diff --git a/llvm/lib/Transforms/Scalar/ConstraintElimination.cpp b/llvm/lib/Transforms/Scalar/ConstraintElimination.cpp index 7e48c28176bd..70bfa469193b 100644 --- a/llvm/lib/Transforms/Scalar/ConstraintElimination.cpp +++ b/llvm/lib/Transforms/Scalar/ConstraintElimination.cpp @@ -554,6 +554,12 @@ static Decomposition decompose(Value *V, V = Op0; } + if (match(V, m_SExt(m_Value(Op0)))) { + V = Op0; + Preconditions.emplace_back(CmpInst::ICMP_SGE, Op0, + ConstantInt::get(Op0->getType(), 0)); + } + Value *Op1; ConstantInt *CI; if (match(V, m_NUWAdd(m_Value(Op0), m_Value(Op1)))) { diff --git a/llvm/test/Transforms/ConstraintElimination/sext-unsigned-predicates.ll b/llvm/test/Transforms/ConstraintElimination/sext-unsigned-predicates.ll index ac3e57768ae5..00dc48ef89c9 100644 --- a/llvm/test/Transforms/ConstraintElimination/sext-unsigned-predicates.ll +++ b/llvm/test/Transforms/ConstraintElimination/sext-unsigned-predicates.ll @@ -13,7 +13,8 @@ define void @uge_sext(i16 %x, i32 %y) { ; CHECK-NEXT: [[AND:%.*]] = and i1 [[C_1]], [[C_2]] ; CHECK-NEXT: br i1 [[AND]], label [[BB1:%.*]], label [[BB2:%.*]] ; CHECK: bb1: -; CHECK-NEXT: call void @use(i1 true) +; CHECK-NEXT: [[T_1:%.*]] = icmp uge i32 [[X_EXT]], [[Y]] +; CHECK-NEXT: call void @use(i1 [[T_1]]) ; CHECK-NEXT: [[C_3:%.*]] = icmp uge i16 [[X]], -10 ; CHECK-NEXT: call void @use(i1 [[C_3]]) ; CHECK-NEXT: [[C_4:%.*]] = icmp uge i32 [[X_EXT]], -9 @@ -65,8 +66,7 @@ define void @uge_sext_known_positive(i16 %x, i32 %y) { ; CHECK-NEXT: br i1 [[AND]], label [[BB1:%.*]], label [[BB2:%.*]] ; CHECK: bb1: ; CHECK-NEXT: call void @use(i1 true) -; CHECK-NEXT: [[T_2:%.*]] = icmp uge i16 [[X]], 10 -; CHECK-NEXT: call void @use(i1 [[T_2]]) +; CHECK-NEXT: call void @use(i1 true) ; CHECK-NEXT: [[C_3:%.*]] = icmp uge i32 [[X_EXT]], 11 ; CHECK-NEXT: call void @use(i1 [[C_3]]) ; CHECK-NEXT: [[C_4:%.*]] = icmp uge i32 [[X_EXT]], 11 diff --git a/llvm/test/Transforms/ConstraintElimination/transfer-signed-facts-to-unsigned.ll b/llvm/test/Transforms/ConstraintElimination/transfer-signed-facts-to-unsigned.ll index 2fe92628dfa3..68e48c7d2944 100644 --- a/llvm/test/Transforms/ConstraintElimination/transfer-signed-facts-to-unsigned.ll +++ b/llvm/test/Transforms/ConstraintElimination/transfer-signed-facts-to-unsigned.ll @@ -503,11 +503,9 @@ define i32 @sge_2_gep(i32 %idx, ptr %src, i32 %idx.2) { ; CHECK-NEXT: [[CMP:%.*]] = icmp sge i32 [[IDX]], 2 ; CHECK-NEXT: call void @llvm.assume(i1 [[CMP]]) ; CHECK-NEXT: [[ADD_PTR_2:%.*]] = getelementptr inbounds i32, ptr [[SRC]], i32 [[IDX_2:%.*]] -; CHECK-NEXT: [[T_1:%.*]] = icmp ult ptr [[SRC]], [[ADD_PTR]] ; CHECK-NEXT: [[C_1:%.*]] = icmp ult ptr [[SRC]], [[ADD_PTR_2]] -; CHECK-NEXT: [[X_1:%.*]] = xor i1 [[T_1]], [[C_1]] -; CHECK-NEXT: [[F_1:%.*]] = icmp uge ptr [[SRC]], [[ADD_PTR]] -; CHECK-NEXT: [[X_2:%.*]] = xor i1 [[X_1]], [[F_1]] +; CHECK-NEXT: [[X_1:%.*]] = xor i1 true, [[C_1]] +; CHECK-NEXT: [[X_2:%.*]] = xor i1 [[X_1]], false ; CHECK-NEXT: br i1 [[X_2]], label [[THEN:%.*]], label [[ELSE:%.*]] ; CHECK: then: ; CHECK-NEXT: ret i32 0 -- GitLab From cf128305bdada3ffb34054813a855d80b3948025 Mon Sep 17 00:00:00 2001 From: Yingwei Zheng Date: Wed, 22 May 2024 20:20:33 +0800 Subject: [PATCH 112/452] [SDAG] Don't treat ISD::SHL as a uniform binary operator in `ShrinkDemandedOp` (#92753) In `TargetLowering::ShrinkDemandedOp`, types of lhs and rhs may differ before legalization. In the original case, `VT` is `i64` and `SmallVT` is `i32`, but the type of rhs is `i8`. Then invalid truncate nodes will be created. See the description of ISD::SHL for further information: > After legalization, the type of the shift amount is known to be TLI.getShiftAmountTy(). Before legalization, the shift amount can be any type, but care must be taken to ensure it is large enough. https://github.com/llvm/llvm-project/blob/605ae4e93be8976095c7eedf5c08bfdb9ff71257/llvm/include/llvm/CodeGen/ISDOpcodes.h#L691-L712 This patch stops handling ISD::SHL in `TargetLowering::ShrinkDemandedOp` and duplicates the logic in `TargetLowering::SimplifyDemandedBits`. Additionally, it adds some additional checks like `isNarrowingProfitable` and `isTypeDesirableForOp` to improve the codegen on AArch64. Fixes https://github.com/llvm/llvm-project/issues/92720. --- .../CodeGen/SelectionDAG/TargetLowering.cpp | 32 ++++- llvm/test/CodeGen/AArch64/bitfield-insert.ll | 11 +- llvm/test/CodeGen/AArch64/trunc-to-tbl.ll | 118 +++++++++--------- llvm/test/CodeGen/X86/pr92720.ll | 15 +++ 4 files changed, 105 insertions(+), 71 deletions(-) create mode 100644 llvm/test/CodeGen/X86/pr92720.ll diff --git a/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp b/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp index b6d4050236b7..87c4c62522c1 100644 --- a/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp @@ -587,6 +587,10 @@ bool TargetLowering::ShrinkDemandedOp(SDValue Op, unsigned BitWidth, if (VT.isVector()) return false; + assert(Op.getOperand(0).getValueType().getScalarSizeInBits() == BitWidth && + Op.getOperand(1).getValueType().getScalarSizeInBits() == BitWidth && + "ShrinkDemandedOp only supports operands that have the same size!"); + // Don't do this if the node has another user, which may require the // full value. if (!Op.getNode()->hasOneUse()) @@ -1832,11 +1836,33 @@ bool TargetLowering::SimplifyDemandedBits( } } + // TODO: Can we merge this fold with the one below? // Try shrinking the operation as long as the shift amount will still be // in range. - if ((ShAmt < DemandedBits.getActiveBits()) && - ShrinkDemandedOp(Op, BitWidth, DemandedBits, TLO)) - return true; + if (ShAmt < DemandedBits.getActiveBits() && !VT.isVector() && + Op.getNode()->hasOneUse()) { + // Search for the smallest integer type with free casts to and from + // Op's type. For expedience, just check power-of-2 integer types. + unsigned DemandedSize = DemandedBits.getActiveBits(); + for (unsigned SmallVTBits = llvm::bit_ceil(DemandedSize); + SmallVTBits < BitWidth; SmallVTBits = NextPowerOf2(SmallVTBits)) { + EVT SmallVT = EVT::getIntegerVT(*TLO.DAG.getContext(), SmallVTBits); + if (isNarrowingProfitable(VT, SmallVT) && + isTypeDesirableForOp(ISD::SHL, SmallVT) && + isTruncateFree(VT, SmallVT) && isZExtFree(SmallVT, VT) && + (!TLO.LegalOperations() || isOperationLegal(ISD::SHL, SmallVT))) { + assert(DemandedSize <= SmallVTBits && + "Narrowed below demanded bits?"); + // We found a type with free casts. + SDValue NarrowShl = TLO.DAG.getNode( + ISD::SHL, dl, SmallVT, + TLO.DAG.getNode(ISD::TRUNCATE, dl, SmallVT, Op.getOperand(0)), + TLO.DAG.getShiftAmountConstant(ShAmt, SmallVT, dl)); + return TLO.CombineTo( + Op, TLO.DAG.getNode(ISD::ANY_EXTEND, dl, VT, NarrowShl)); + } + } + } // Narrow shift to lower half - similar to ShrinkDemandedOp. // (shl i64:x, K) -> (i64 zero_extend (shl (i32 (trunc i64:x)), K)) diff --git a/llvm/test/CodeGen/AArch64/bitfield-insert.ll b/llvm/test/CodeGen/AArch64/bitfield-insert.ll index 30b5e86c1e6d..14a594e8028d 100644 --- a/llvm/test/CodeGen/AArch64/bitfield-insert.ll +++ b/llvm/test/CodeGen/AArch64/bitfield-insert.ll @@ -193,11 +193,10 @@ define void @test_64bit_badmask(ptr %existing, ptr %new) { ; CHECK: // %bb.0: ; CHECK-NEXT: ldr x8, [x0] ; CHECK-NEXT: ldr x9, [x1] -; CHECK-NEXT: mov w10, #135 // =0x87 -; CHECK-NEXT: mov w11, #664 // =0x298 -; CHECK-NEXT: lsl w9, w9, #3 -; CHECK-NEXT: and x8, x8, x10 -; CHECK-NEXT: and x9, x9, x11 +; CHECK-NEXT: mov w10, #664 // =0x298 +; CHECK-NEXT: mov w11, #135 // =0x87 +; CHECK-NEXT: and x9, x10, x9, lsl #3 +; CHECK-NEXT: and x8, x8, x11 ; CHECK-NEXT: orr x8, x8, x9 ; CHECK-NEXT: str x8, [x0] ; CHECK-NEXT: ret @@ -579,7 +578,6 @@ define <2 x i32> @test_complex_type(ptr %addr, i64 %in, ptr %bf ) { define i64 @test_truncated_shift(i64 %x, i64 %y) { ; CHECK-LABEL: test_truncated_shift: ; CHECK: // %bb.0: // %entry -; CHECK-NEXT: // kill: def $w1 killed $w1 killed $x1 def $x1 ; CHECK-NEXT: bfi x0, x1, #25, #5 ; CHECK-NEXT: ret entry: @@ -593,7 +591,6 @@ entry: define i64 @test_and_extended_shift_with_imm(i64 %0) { ; CHECK-LABEL: test_and_extended_shift_with_imm: ; CHECK: // %bb.0: -; CHECK-NEXT: // kill: def $w0 killed $w0 killed $x0 def $x0 ; CHECK-NEXT: ubfiz x0, x0, #7, #8 ; CHECK-NEXT: ret %2 = shl i64 %0, 7 diff --git a/llvm/test/CodeGen/AArch64/trunc-to-tbl.ll b/llvm/test/CodeGen/AArch64/trunc-to-tbl.ll index 18cd4cc2111a..c4a58ba12dc6 100644 --- a/llvm/test/CodeGen/AArch64/trunc-to-tbl.ll +++ b/llvm/test/CodeGen/AArch64/trunc-to-tbl.ll @@ -571,29 +571,27 @@ define void @trunc_v8i19_to_v8i8_in_loop(ptr %A, ptr %dst) { ; CHECK-NEXT: mov x8, xzr ; CHECK-NEXT: LBB5_1: ; %loop ; CHECK-NEXT: ; =>This Inner Loop Header: Depth=1 -; CHECK-NEXT: ldp x10, x9, [x0] -; CHECK-NEXT: ldrb w13, [x0, #18] -; CHECK-NEXT: ldrh w14, [x0, #16] +; CHECK-NEXT: ldp x9, x10, [x0] +; CHECK-NEXT: ldrb w14, [x0, #18] +; CHECK-NEXT: ldrh w15, [x0, #16] ; CHECK-NEXT: add x0, x0, #32 -; CHECK-NEXT: ubfx x12, x9, #12, #20 -; CHECK-NEXT: fmov s0, w10 -; CHECK-NEXT: lsr x11, x10, #19 -; CHECK-NEXT: lsr x15, x9, #31 -; CHECK-NEXT: fmov s1, w12 -; CHECK-NEXT: lsr x12, x9, #50 -; CHECK-NEXT: mov.s v0[1], w11 -; CHECK-NEXT: orr w11, w14, w13, lsl #16 -; CHECK-NEXT: lsr x13, x10, #38 -; CHECK-NEXT: lsr x10, x10, #57 -; CHECK-NEXT: mov.s v1[1], w15 -; CHECK-NEXT: orr w12, w12, w11, lsl #14 -; CHECK-NEXT: orr w9, w10, w9, lsl #7 -; CHECK-NEXT: lsr w10, w11, #5 -; CHECK-NEXT: mov.s v0[2], w13 +; CHECK-NEXT: ubfx x12, x10, #12, #20 +; CHECK-NEXT: fmov s1, w9 +; CHECK-NEXT: lsr x11, x9, #19 +; CHECK-NEXT: lsr x13, x10, #31 +; CHECK-NEXT: fmov s0, w12 +; CHECK-NEXT: lsr x12, x9, #38 +; CHECK-NEXT: extr x9, x10, x9, #57 +; CHECK-NEXT: mov.s v1[1], w11 +; CHECK-NEXT: orr x11, x15, x14, lsl #16 +; CHECK-NEXT: mov.s v0[1], w13 +; CHECK-NEXT: extr x13, x11, x10, #50 +; CHECK-NEXT: ubfx x10, x11, #5, #27 ; CHECK-NEXT: mov.s v1[2], w12 -; CHECK-NEXT: mov.s v0[3], w9 -; CHECK-NEXT: mov.s v1[3], w10 -; CHECK-NEXT: uzp1.8h v0, v0, v1 +; CHECK-NEXT: mov.s v0[2], w13 +; CHECK-NEXT: mov.s v1[3], w9 +; CHECK-NEXT: mov.s v0[3], w10 +; CHECK-NEXT: uzp1.8h v0, v1, v0 ; CHECK-NEXT: xtn.8b v0, v0 ; CHECK-NEXT: str d0, [x1, x8, lsl #3] ; CHECK-NEXT: add x8, x8, #1 @@ -608,35 +606,34 @@ define void @trunc_v8i19_to_v8i8_in_loop(ptr %A, ptr %dst) { ; CHECK-BE-NEXT: .LBB5_1: // %loop ; CHECK-BE-NEXT: // =>This Inner Loop Header: Depth=1 ; CHECK-BE-NEXT: ldp x10, x9, [x0] -; CHECK-BE-NEXT: ldrb w16, [x0, #18] -; CHECK-BE-NEXT: lsr x11, x9, #40 -; CHECK-BE-NEXT: ubfx x12, x9, #33, #7 -; CHECK-BE-NEXT: lsr x15, x10, #45 -; CHECK-BE-NEXT: lsr x13, x10, #40 -; CHECK-BE-NEXT: ubfx x14, x10, #26, #14 -; CHECK-BE-NEXT: orr w11, w12, w11, lsl #7 -; CHECK-BE-NEXT: ldrh w12, [x0, #16] -; CHECK-BE-NEXT: fmov s0, w15 -; CHECK-BE-NEXT: orr w13, w14, w13, lsl #14 -; CHECK-BE-NEXT: ubfx x14, x9, #14, #18 +; CHECK-BE-NEXT: ldrh w16, [x0, #16] +; CHECK-BE-NEXT: ldrb w17, [x0, #18] ; CHECK-BE-NEXT: add x0, x0, #32 -; CHECK-BE-NEXT: fmov s1, w11 -; CHECK-BE-NEXT: orr w11, w16, w12, lsl #8 -; CHECK-BE-NEXT: lsl x12, x9, #24 -; CHECK-BE-NEXT: mov v0.s[1], w13 +; CHECK-BE-NEXT: lsl x11, x9, #24 +; CHECK-BE-NEXT: lsr x12, x9, #40 +; CHECK-BE-NEXT: lsr x13, x10, #45 +; CHECK-BE-NEXT: lsl x14, x10, #24 +; CHECK-BE-NEXT: lsr x15, x10, #40 +; CHECK-BE-NEXT: extr x12, x12, x11, #57 +; CHECK-BE-NEXT: fmov s0, w13 ; CHECK-BE-NEXT: ubfx x13, x10, #7, #25 +; CHECK-BE-NEXT: extr x14, x15, x14, #50 +; CHECK-BE-NEXT: ubfx x15, x9, #14, #18 ; CHECK-BE-NEXT: extr x9, x10, x9, #40 -; CHECK-BE-NEXT: orr w12, w11, w12 -; CHECK-BE-NEXT: mov v1.s[1], w14 -; CHECK-BE-NEXT: lsr w12, w12, #19 +; CHECK-BE-NEXT: fmov s1, w12 +; CHECK-BE-NEXT: orr w12, w17, w16, lsl #8 +; CHECK-BE-NEXT: mov v0.s[1], w14 ; CHECK-BE-NEXT: ubfx x9, x9, #12, #20 +; CHECK-BE-NEXT: orr w11, w12, w11 +; CHECK-BE-NEXT: mov v1.s[1], w15 +; CHECK-BE-NEXT: lsr w11, w11, #19 ; CHECK-BE-NEXT: mov v0.s[2], w13 -; CHECK-BE-NEXT: mov v1.s[2], w12 +; CHECK-BE-NEXT: mov v1.s[2], w11 ; CHECK-BE-NEXT: mov v0.s[3], w9 ; CHECK-BE-NEXT: add x9, x1, x8, lsl #3 ; CHECK-BE-NEXT: add x8, x8, #1 ; CHECK-BE-NEXT: cmp x8, #1000 -; CHECK-BE-NEXT: mov v1.s[3], w11 +; CHECK-BE-NEXT: mov v1.s[3], w12 ; CHECK-BE-NEXT: uzp1 v0.8h, v0.8h, v1.8h ; CHECK-BE-NEXT: xtn v0.8b, v0.8h ; CHECK-BE-NEXT: st1 { v0.8b }, [x9] @@ -650,35 +647,34 @@ define void @trunc_v8i19_to_v8i8_in_loop(ptr %A, ptr %dst) { ; CHECK-DISABLE-NEXT: .LBB5_1: // %loop ; CHECK-DISABLE-NEXT: // =>This Inner Loop Header: Depth=1 ; CHECK-DISABLE-NEXT: ldp x10, x9, [x0] -; CHECK-DISABLE-NEXT: ldrb w16, [x0, #18] -; CHECK-DISABLE-NEXT: lsr x11, x9, #40 -; CHECK-DISABLE-NEXT: ubfx x12, x9, #33, #7 -; CHECK-DISABLE-NEXT: lsr x15, x10, #45 -; CHECK-DISABLE-NEXT: lsr x13, x10, #40 -; CHECK-DISABLE-NEXT: ubfx x14, x10, #26, #14 -; CHECK-DISABLE-NEXT: orr w11, w12, w11, lsl #7 -; CHECK-DISABLE-NEXT: ldrh w12, [x0, #16] -; CHECK-DISABLE-NEXT: fmov s0, w15 -; CHECK-DISABLE-NEXT: orr w13, w14, w13, lsl #14 -; CHECK-DISABLE-NEXT: ubfx x14, x9, #14, #18 +; CHECK-DISABLE-NEXT: ldrh w16, [x0, #16] +; CHECK-DISABLE-NEXT: ldrb w17, [x0, #18] ; CHECK-DISABLE-NEXT: add x0, x0, #32 -; CHECK-DISABLE-NEXT: fmov s1, w11 -; CHECK-DISABLE-NEXT: orr w11, w16, w12, lsl #8 -; CHECK-DISABLE-NEXT: lsl x12, x9, #24 -; CHECK-DISABLE-NEXT: mov v0.s[1], w13 +; CHECK-DISABLE-NEXT: lsl x11, x9, #24 +; CHECK-DISABLE-NEXT: lsr x12, x9, #40 +; CHECK-DISABLE-NEXT: lsr x13, x10, #45 +; CHECK-DISABLE-NEXT: lsl x14, x10, #24 +; CHECK-DISABLE-NEXT: lsr x15, x10, #40 +; CHECK-DISABLE-NEXT: extr x12, x12, x11, #57 +; CHECK-DISABLE-NEXT: fmov s0, w13 ; CHECK-DISABLE-NEXT: ubfx x13, x10, #7, #25 +; CHECK-DISABLE-NEXT: extr x14, x15, x14, #50 +; CHECK-DISABLE-NEXT: ubfx x15, x9, #14, #18 ; CHECK-DISABLE-NEXT: extr x9, x10, x9, #40 -; CHECK-DISABLE-NEXT: orr w12, w11, w12 -; CHECK-DISABLE-NEXT: mov v1.s[1], w14 -; CHECK-DISABLE-NEXT: lsr w12, w12, #19 +; CHECK-DISABLE-NEXT: fmov s1, w12 +; CHECK-DISABLE-NEXT: orr w12, w17, w16, lsl #8 +; CHECK-DISABLE-NEXT: mov v0.s[1], w14 ; CHECK-DISABLE-NEXT: ubfx x9, x9, #12, #20 +; CHECK-DISABLE-NEXT: orr w11, w12, w11 +; CHECK-DISABLE-NEXT: mov v1.s[1], w15 +; CHECK-DISABLE-NEXT: lsr w11, w11, #19 ; CHECK-DISABLE-NEXT: mov v0.s[2], w13 -; CHECK-DISABLE-NEXT: mov v1.s[2], w12 +; CHECK-DISABLE-NEXT: mov v1.s[2], w11 ; CHECK-DISABLE-NEXT: mov v0.s[3], w9 ; CHECK-DISABLE-NEXT: add x9, x1, x8, lsl #3 ; CHECK-DISABLE-NEXT: add x8, x8, #1 ; CHECK-DISABLE-NEXT: cmp x8, #1000 -; CHECK-DISABLE-NEXT: mov v1.s[3], w11 +; CHECK-DISABLE-NEXT: mov v1.s[3], w12 ; CHECK-DISABLE-NEXT: uzp1 v0.8h, v0.8h, v1.8h ; CHECK-DISABLE-NEXT: xtn v0.8b, v0.8h ; CHECK-DISABLE-NEXT: st1 { v0.8b }, [x9] diff --git a/llvm/test/CodeGen/X86/pr92720.ll b/llvm/test/CodeGen/X86/pr92720.ll new file mode 100644 index 000000000000..b2543c08328c --- /dev/null +++ b/llvm/test/CodeGen/X86/pr92720.ll @@ -0,0 +1,15 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 5 +; RUN: llc < %s -mtriple=x86_64-linux-gnu | FileCheck %s + +; Make sure we don't crash when shrinking the shift amount before legalization. +define i64 @pr92720(i64 %x) { +; CHECK-LABEL: pr92720: +; CHECK: # %bb.0: +; CHECK-NEXT: movabsq $8589934592, %rax # imm = 0x200000000 +; CHECK-NEXT: retq + %or = or i64 %x, 255 + %sub = sub i64 0, %or + %shl = shl i64 1, %sub + %sext = shl i64 %shl, 32 + ret i64 %sext +} -- GitLab From 2aa218c247eef03f4ea922d635b7a9f46d061119 Mon Sep 17 00:00:00 2001 From: Krzysztof Parzyszek Date: Wed, 22 May 2024 07:23:14 -0500 Subject: [PATCH 113/452] [flang][OpenMP] Diagnose invalid reduction modifiers (#92406) Emit diagnostic messages for invalid modifiers in "reduction" clause. Fixes https://github.com/llvm/llvm-project/issues/92397 --- flang/lib/Semantics/check-omp-structure.cpp | 59 ++++++++++++ flang/lib/Semantics/check-omp-structure.h | 1 + .../OpenMP/invalid-reduction-modifier.f90 | 4 +- .../Semantics/OpenMP/reduction-modifiers.f90 | 89 +++++++++++++++++++ 4 files changed, 150 insertions(+), 3 deletions(-) create mode 100644 flang/test/Semantics/OpenMP/reduction-modifiers.f90 diff --git a/flang/lib/Semantics/check-omp-structure.cpp b/flang/lib/Semantics/check-omp-structure.cpp index e9637b7bb591..5e3a5725c18d 100644 --- a/flang/lib/Semantics/check-omp-structure.cpp +++ b/flang/lib/Semantics/check-omp-structure.cpp @@ -2310,6 +2310,7 @@ void OmpStructureChecker::Enter(const parser::OmpClause::Reduction &x) { if (CheckReductionOperators(x)) { CheckReductionTypeList(x); } + CheckReductionModifier(x); } bool OmpStructureChecker::CheckReductionOperators( @@ -2394,6 +2395,64 @@ void OmpStructureChecker::CheckReductionTypeList( } } +void OmpStructureChecker::CheckReductionModifier( + const parser::OmpClause::Reduction &x) { + using ReductionModifier = parser::OmpReductionClause::ReductionModifier; + const auto &maybeModifier{std::get>(x.v.t)}; + if (!maybeModifier || *maybeModifier == ReductionModifier::Default) { + // No modifier, or the default one is always ok. + return; + } + ReductionModifier modifier{*maybeModifier}; + const DirectiveContext &dirCtx{GetContext()}; + if (dirCtx.directive == llvm::omp::Directive::OMPD_loop) { + // [5.2:257:33-34] + // If a reduction-modifier is specified in a reduction clause that + // appears on the directive, then the reduction modifier must be + // default. + context_.Say(GetContext().clauseSource, + "REDUCTION modifier on LOOP directive must be DEFAULT"_err_en_US); + } + if (modifier == ReductionModifier::Task) { + // "Task" is only allowed on worksharing or "parallel" directive. + static llvm::omp::Directive worksharing[]{ + llvm::omp::Directive::OMPD_do, llvm::omp::Directive::OMPD_scope, + llvm::omp::Directive::OMPD_sections, + // There are more worksharing directives, but they do not apply: + // "for" is C++ only, + // "single" and "workshare" don't allow reduction clause, + // "loop" has different restrictions (checked above). + }; + if (dirCtx.directive != llvm::omp::Directive::OMPD_parallel && + !llvm::is_contained(worksharing, dirCtx.directive)) { + context_.Say(GetContext().clauseSource, + "Modifier 'TASK' on REDUCTION clause is only allowed with " + "PARALLEL or worksharing directive"_err_en_US); + } + } else if (modifier == ReductionModifier::Inscan) { + // "Inscan" is only allowed on worksharing-loop, worksharing-loop simd, + // or "simd" directive. + // The worksharing-loop directives are OMPD_do and OMPD_for. Only the + // former is allowed in Fortran. + switch (dirCtx.directive) { + case llvm::omp::Directive::OMPD_do: // worksharing-loop + case llvm::omp::Directive::OMPD_do_simd: // worksharing-loop simd + case llvm::omp::Directive::OMPD_simd: // "simd" + break; + default: + context_.Say(GetContext().clauseSource, + "Modifier 'INSCAN' on REDUCTION clause is only allowed with " + "worksharing-loop, worksharing-loop simd, " + "or SIMD directive"_err_en_US); + } + } else { + // Catch-all for potential future modifiers to make sure that this + // function is up-to-date. + context_.Say(GetContext().clauseSource, + "Unexpected modifier on REDUCTION clause"_err_en_US); + } +} + void OmpStructureChecker::CheckIntentInPointerAndDefinable( const parser::OmpObjectList &objectList, const llvm::omp::Clause clause) { for (const auto &ompObject : objectList.v) { diff --git a/flang/lib/Semantics/check-omp-structure.h b/flang/lib/Semantics/check-omp-structure.h index 1f7284307703..47705771e8e2 100644 --- a/flang/lib/Semantics/check-omp-structure.h +++ b/flang/lib/Semantics/check-omp-structure.h @@ -205,6 +205,7 @@ private: bool CheckIntrinsicOperator( const parser::DefinedOperator::IntrinsicOperator &); void CheckReductionTypeList(const parser::OmpClause::Reduction &); + void CheckReductionModifier(const parser::OmpClause::Reduction &); void CheckMasterNesting(const parser::OpenMPBlockConstruct &x); void ChecksOnOrderedAsBlock(); void CheckBarrierNesting(const parser::OpenMPSimpleStandaloneConstruct &x); diff --git a/flang/test/Lower/OpenMP/invalid-reduction-modifier.f90 b/flang/test/Lower/OpenMP/invalid-reduction-modifier.f90 index 53871276761f..b3e87df7086e 100644 --- a/flang/test/Lower/OpenMP/invalid-reduction-modifier.f90 +++ b/flang/test/Lower/OpenMP/invalid-reduction-modifier.f90 @@ -1,6 +1,4 @@ -!Remove the --crash below once we can diagnose the issue more gracefully. -!REQUIRES: asserts -!RUN: not --crash %flang_fc1 -fopenmp -emit-hlfir -o - %s +!RUN: not %flang_fc1 -fopenmp -emit-hlfir -o - %s ! Check that we reject the "task" reduction modifier on the "simd" directive. diff --git a/flang/test/Semantics/OpenMP/reduction-modifiers.f90 b/flang/test/Semantics/OpenMP/reduction-modifiers.f90 new file mode 100644 index 000000000000..cf38200ba0a8 --- /dev/null +++ b/flang/test/Semantics/OpenMP/reduction-modifiers.f90 @@ -0,0 +1,89 @@ +! RUN: %python %S/../test_errors.py %s %flang_fc1 -fopenmp -fopenmp-version=52 + +subroutine mod_task1(x) + integer, intent(inout) :: x + + !Correct: "parallel" directive. + !$omp parallel reduction(task, +:x) + do i = 1, 100 + x = foo(i) + enddo + !$omp end parallel +end + +subroutine mod_task2(x) + integer, intent(inout) :: x + + !Correct: worksharing directive. + !$omp sections reduction(task, +:x) + do i = 1, 100 + x = foo(i) + enddo + !$omp end sections +end + +subroutine mod_task3(x) + integer, intent(inout) :: x + + !ERROR: Modifier 'TASK' on REDUCTION clause is only allowed with PARALLEL or worksharing directive + !$omp simd reduction(task, +:x) + do i = 1, 100 + x = foo(i) + enddo + !$omp end simd +end + +subroutine mod_inscan1(x) + integer, intent(inout) :: x + + !Correct: worksharing-loop directive + !$omp do reduction(inscan, +:x) + do i = 1, 100 + x = foo(i) + enddo + !$omp end do +end + +subroutine mod_inscan2(x) + integer, intent(inout) :: x + + !Correct: worksharing-loop simd directive + !$omp do simd reduction(inscan, +:x) + do i = 1, 100 + x = foo(i) + enddo + !$omp end do simd +end + +subroutine mod_inscan3(x) + integer, intent(inout) :: x + + !Correct: "simd" directive + !$omp simd reduction(inscan, +:x) + do i = 1, 100 + x = foo(i) + enddo + !$omp end simd +end + +subroutine mod_inscan4(x) + integer, intent(inout) :: x + + !ERROR: Modifier 'INSCAN' on REDUCTION clause is only allowed with worksharing-loop, worksharing-loop simd, or SIMD directive + !$omp parallel reduction(inscan, +:x) + do i = 1, 100 + x = foo(i) + enddo + !$omp end parallel +end + +subroutine mod_inscan5(x) + integer, intent(inout) :: x + + !ERROR: Modifier 'INSCAN' on REDUCTION clause is only allowed with worksharing-loop, worksharing-loop simd, or SIMD directive + !$omp sections reduction(inscan, +:x) + do i = 1, 100 + x = foo(i) + enddo + !$omp end sections +end -- GitLab From 71b1fbdff6cf567ad278c51f0acdcdf23de0ac28 Mon Sep 17 00:00:00 2001 From: Michael Maitland Date: Wed, 22 May 2024 08:27:35 -0400 Subject: [PATCH 114/452] [MISched][NFC] Add documentation comment in pickNode for ReadyQueue maintenence (#92976) I had some trouble understanding why `removeReady` removed nodes from the Pending queue, since my intuition told me that the Pending queue did not represent a node that was ready. I took a deeper look and found that pickOnlyNode and pickNodeFromQueue only picked nodes from the Available queue too. I found that need to nodes from the Available and Pending queues that correspond to the opposite direction that we ended up choosing from (IsTopNode vs !IsTopNode). It took me a little longer than I would have liked to understand this fact, so I figured that I would add a comment in the code that makes it clear for future readers. --- llvm/lib/CodeGen/MachineScheduler.cpp | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/llvm/lib/CodeGen/MachineScheduler.cpp b/llvm/lib/CodeGen/MachineScheduler.cpp index 0858be64de40..03e892a5e0d2 100644 --- a/llvm/lib/CodeGen/MachineScheduler.cpp +++ b/llvm/lib/CodeGen/MachineScheduler.cpp @@ -3777,6 +3777,21 @@ SUnit *GenericScheduler::pickNode(bool &IsTopNode) { } } while (SU->isScheduled); + // If IsTopNode, then SU is in Top.Available and must be removed. Otherwise, + // if isTopReady(), then SU is in either Top.Available or Top.Pending. + // If !IsTopNode, then SU is in Bot.Available and must be removed. Otherwise, + // if isBottomReady(), then SU is in either Bot.Available or Bot.Pending. + // + // It is coincidental when !IsTopNode && isTopReady or when IsTopNode && + // isBottomReady. That is, it didn't factor into the decision to choose SU + // because it isTopReady or isBottomReady, respectively. In fact, if the + // RegionPolicy is OnlyTopDown or OnlyBottomUp, then the Bot queues and Top + // queues respectivley contain the original roots and don't get updated when + // picking a node. So if SU isTopReady on a OnlyBottomUp pick, then it was + // because we schduled everything but the top roots. Conversley, if SU + // isBottomReady on OnlyTopDown, then it was because we scheduled everything + // but the bottom roots. If its in a queue even coincidentally, it should be + // removed so it does not get re-picked in a subsequent pickNode call. if (SU->isTopReady()) Top.removeReady(SU); if (SU->isBottomReady()) -- GitLab From 9120562dfcc09cb4caf3052c6744049b4d9c8481 Mon Sep 17 00:00:00 2001 From: Michael Kruse Date: Wed, 22 May 2024 14:30:31 +0200 Subject: [PATCH 115/452] [Clang][OpenMP] Enable tile/unroll on iterator- and foreach-loops (#91459) OpenMP loop transformation did not work on a for-loop using an iterator or range-based for-loops. The first reason is that it combined the iterator's type for generated loops with the type of `NumIterations` as generated for any `OMPLoopBasedDirective` which is an integer. Fixed by basing all generated loop variables on `NumIterations`. Second, C++11 range-based for-loops include syntactic sugar that needs to be executed before the loop. This additional code is now added to the construct's Pre-Init lists. Third, C++20 added an initializer statement to range-based for-loops which is also added to the pre-init statement. PreInits used to be a `DeclStmt` which made it difficult to add arbitrary statements from `CXXRangeForStmt`'s syntactic sugar, especially the for-loops init statement which does not need to be a declaration. Change it to be a general `Stmt` that can be a `CompoundStmt` to hold arbitrary Stmts, including DeclStmts. This also avoids the `PointerUnion` workaround used by `checkTransformableLoopNest`. End-to-end tests are added to verify the expected number and order of loop execution and evaluations of expressions (such as iterator dereference). The order and number of evaluations of expressions in canonical loops is explicitly undefined by OpenMP but checked here for clarification and for changes to be noticed. --- clang/include/clang/Sema/SemaOpenMP.h | 4 +- clang/lib/CodeGen/CGStmtOpenMP.cpp | 29 +- clang/lib/Sema/SemaOpenMP.cpp | 197 ++-- clang/test/OpenMP/tile_codegen.cpp | 887 +++++++++++++----- .../OpenMP/tile_codegen_for_dependent.cpp | 130 +-- clang/test/OpenMP/tile_codegen_tile_for.cpp | 218 ++--- openmp/runtime/test/lit.cfg | 4 + .../runtime/test/transform/tile/foreach.cpp | 228 +++++ .../runtime/test/transform/tile/iterfor.cpp | 233 +++++ .../tile/parallel-wsloop-collapse-foreach.cpp | 366 ++++++++ .../test/transform/unroll/factor_foreach.cpp | 162 ++++ .../test/transform/unroll/factor_intfor.c | 25 + .../test/transform/unroll/factor_iterfor.cpp | 169 ++++ ...actor_parallel-wsloop-collapse-foreach.cpp | 199 ++++ ...factor_parallel-wsloop-collapse-intfor.cpp | 32 + .../test/transform/unroll/full_intfor.c | 25 + .../test/transform/unroll/heuristic_intfor.c | 25 + .../test/transform/unroll/partial_intfor.c | 25 + 18 files changed, 2511 insertions(+), 447 deletions(-) create mode 100644 openmp/runtime/test/transform/tile/foreach.cpp create mode 100644 openmp/runtime/test/transform/tile/iterfor.cpp create mode 100644 openmp/runtime/test/transform/tile/parallel-wsloop-collapse-foreach.cpp create mode 100644 openmp/runtime/test/transform/unroll/factor_foreach.cpp create mode 100644 openmp/runtime/test/transform/unroll/factor_intfor.c create mode 100644 openmp/runtime/test/transform/unroll/factor_iterfor.cpp create mode 100644 openmp/runtime/test/transform/unroll/factor_parallel-wsloop-collapse-foreach.cpp create mode 100644 openmp/runtime/test/transform/unroll/factor_parallel-wsloop-collapse-intfor.cpp create mode 100644 openmp/runtime/test/transform/unroll/full_intfor.c create mode 100644 openmp/runtime/test/transform/unroll/heuristic_intfor.c create mode 100644 openmp/runtime/test/transform/unroll/partial_intfor.c diff --git a/clang/include/clang/Sema/SemaOpenMP.h b/clang/include/clang/Sema/SemaOpenMP.h index 9927459bbc59..51981e1c9a8b 100644 --- a/clang/include/clang/Sema/SemaOpenMP.h +++ b/clang/include/clang/Sema/SemaOpenMP.h @@ -1390,9 +1390,7 @@ private: bool checkTransformableLoopNest( OpenMPDirectiveKind Kind, Stmt *AStmt, int NumLoops, SmallVectorImpl &LoopHelpers, - Stmt *&Body, - SmallVectorImpl, 0>> - &OriginalInits); + Stmt *&Body, SmallVectorImpl> &OriginalInits); /// Helper to keep information about the current `omp begin/end declare /// variant` nesting. diff --git a/clang/lib/CodeGen/CGStmtOpenMP.cpp b/clang/lib/CodeGen/CGStmtOpenMP.cpp index eac5ef326293..6410f9e102c9 100644 --- a/clang/lib/CodeGen/CGStmtOpenMP.cpp +++ b/clang/lib/CodeGen/CGStmtOpenMP.cpp @@ -142,7 +142,7 @@ public: /// of used expression from loop statement. class OMPLoopScope : public CodeGenFunction::RunCleanupsScope { void emitPreInitStmt(CodeGenFunction &CGF, const OMPLoopBasedDirective &S) { - const DeclStmt *PreInits; + const Stmt *PreInits; CodeGenFunction::OMPMapVars PreCondVars; if (auto *LD = dyn_cast(&S)) { llvm::DenseSet EmittedAsPrivate; @@ -182,17 +182,34 @@ class OMPLoopScope : public CodeGenFunction::RunCleanupsScope { } return false; }); - PreInits = cast_or_null(LD->getPreInits()); + PreInits = LD->getPreInits(); } else if (const auto *Tile = dyn_cast(&S)) { - PreInits = cast_or_null(Tile->getPreInits()); + PreInits = Tile->getPreInits(); } else if (const auto *Unroll = dyn_cast(&S)) { - PreInits = cast_or_null(Unroll->getPreInits()); + PreInits = Unroll->getPreInits(); } else { llvm_unreachable("Unknown loop-based directive kind."); } if (PreInits) { - for (const auto *I : PreInits->decls()) - CGF.EmitVarDecl(cast(*I)); + // CompoundStmts and DeclStmts are used as lists of PreInit statements and + // declarations. Since declarations must be visible in the the following + // that they initialize, unpack the ComboundStmt they are nested in. + SmallVector PreInitStmts; + if (auto *PreInitCompound = dyn_cast(PreInits)) + llvm::append_range(PreInitStmts, PreInitCompound->body()); + else + PreInitStmts.push_back(PreInits); + + for (const Stmt *S : PreInitStmts) { + // EmitStmt skips any OMPCapturedExprDecls, but needs to be emitted + // here. + if (auto *PreInitDecl = dyn_cast(S)) { + for (Decl *I : PreInitDecl->decls()) + CGF.EmitVarDecl(cast(*I)); + continue; + } + CGF.EmitStmt(S); + } } PreCondVars.restore(CGF); } diff --git a/clang/lib/Sema/SemaOpenMP.cpp b/clang/lib/Sema/SemaOpenMP.cpp index 6110e5229b07..bab61e8fd54e 100644 --- a/clang/lib/Sema/SemaOpenMP.cpp +++ b/clang/lib/Sema/SemaOpenMP.cpp @@ -9815,6 +9815,25 @@ static Stmt *buildPreInits(ASTContext &Context, return nullptr; } +/// Append the \p Item or the content of a CompoundStmt to the list \p +/// TargetList. +/// +/// A CompoundStmt is used as container in case multiple statements need to be +/// stored in lieu of using an explicit list. Flattening is necessary because +/// contained DeclStmts need to be visible after the execution of the list. Used +/// for OpenMP pre-init declarations/statements. +static void appendFlattendedStmtList(SmallVectorImpl &TargetList, + Stmt *Item) { + // nullptr represents an empty list. + if (!Item) + return; + + if (auto *CS = dyn_cast(Item)) + llvm::append_range(TargetList, CS->body()); + else + TargetList.push_back(Item); +} + /// Build preinits statement for the given declarations. static Stmt * buildPreInits(ASTContext &Context, @@ -9828,6 +9847,17 @@ buildPreInits(ASTContext &Context, return nullptr; } +/// Build pre-init statement for the given statements. +static Stmt *buildPreInits(ASTContext &Context, ArrayRef PreInits) { + if (PreInits.empty()) + return nullptr; + + SmallVector Stmts; + for (Stmt *S : PreInits) + appendFlattendedStmtList(Stmts, S); + return CompoundStmt::Create(Context, PreInits, FPOptionsOverride(), {}, {}); +} + /// Build postupdate expression for the given list of postupdates expressions. static Expr *buildPostUpdate(Sema &S, ArrayRef PostUpdates) { Expr *PostUpdate = nullptr; @@ -9924,11 +9954,21 @@ checkOpenMPLoop(OpenMPDirectiveKind DKind, Expr *CollapseLoopCountExpr, Stmt *DependentPreInits = Transform->getPreInits(); if (!DependentPreInits) return; - for (Decl *C : cast(DependentPreInits)->getDeclGroup()) { - auto *D = cast(C); - DeclRefExpr *Ref = buildDeclRefExpr(SemaRef, D, D->getType(), - Transform->getBeginLoc()); - Captures[Ref] = Ref; + + // Search for pre-init declared variables that need to be captured + // to be referenceable inside the directive. + SmallVector Constituents; + appendFlattendedStmtList(Constituents, DependentPreInits); + for (Stmt *S : Constituents) { + if (auto *DC = dyn_cast(S)) { + for (Decl *C : DC->decls()) { + auto *D = cast(C); + DeclRefExpr *Ref = buildDeclRefExpr( + SemaRef, D, D->getType().getNonReferenceType(), + Transform->getBeginLoc()); + Captures[Ref] = Ref; + } + } } })) return 0; @@ -15059,9 +15099,7 @@ StmtResult SemaOpenMP::ActOnOpenMPTargetTeamsDistributeSimdDirective( bool SemaOpenMP::checkTransformableLoopNest( OpenMPDirectiveKind Kind, Stmt *AStmt, int NumLoops, SmallVectorImpl &LoopHelpers, - Stmt *&Body, - SmallVectorImpl, 0>> - &OriginalInits) { + Stmt *&Body, SmallVectorImpl> &OriginalInits) { OriginalInits.emplace_back(); bool Result = OMPLoopBasedDirective::doForAllLoops( AStmt->IgnoreContainers(), /*TryImperfectlyNestedLoops=*/false, NumLoops, @@ -15095,16 +15133,70 @@ bool SemaOpenMP::checkTransformableLoopNest( DependentPreInits = Dir->getPreInits(); else llvm_unreachable("Unhandled loop transformation"); - if (!DependentPreInits) - return; - llvm::append_range(OriginalInits.back(), - cast(DependentPreInits)->getDeclGroup()); + + appendFlattendedStmtList(OriginalInits.back(), DependentPreInits); }); assert(OriginalInits.back().empty() && "No preinit after innermost loop"); OriginalInits.pop_back(); return Result; } +/// Add preinit statements that need to be propageted from the selected loop. +static void addLoopPreInits(ASTContext &Context, + OMPLoopBasedDirective::HelperExprs &LoopHelper, + Stmt *LoopStmt, ArrayRef OriginalInit, + SmallVectorImpl &PreInits) { + + // For range-based for-statements, ensure that their syntactic sugar is + // executed by adding them as pre-init statements. + if (auto *CXXRangeFor = dyn_cast(LoopStmt)) { + Stmt *RangeInit = CXXRangeFor->getInit(); + if (RangeInit) + PreInits.push_back(RangeInit); + + DeclStmt *RangeStmt = CXXRangeFor->getRangeStmt(); + PreInits.push_back(new (Context) DeclStmt(RangeStmt->getDeclGroup(), + RangeStmt->getBeginLoc(), + RangeStmt->getEndLoc())); + + DeclStmt *RangeEnd = CXXRangeFor->getEndStmt(); + PreInits.push_back(new (Context) DeclStmt(RangeEnd->getDeclGroup(), + RangeEnd->getBeginLoc(), + RangeEnd->getEndLoc())); + } + + llvm::append_range(PreInits, OriginalInit); + + // List of OMPCapturedExprDecl, for __begin, __end, and NumIterations + if (auto *PI = cast_or_null(LoopHelper.PreInits)) { + PreInits.push_back(new (Context) DeclStmt( + PI->getDeclGroup(), PI->getBeginLoc(), PI->getEndLoc())); + } + + // Gather declarations for the data members used as counters. + for (Expr *CounterRef : LoopHelper.Counters) { + auto *CounterDecl = cast(CounterRef)->getDecl(); + if (isa(CounterDecl)) + PreInits.push_back(new (Context) DeclStmt( + DeclGroupRef(CounterDecl), SourceLocation(), SourceLocation())); + } +} + +/// Collect the loop statements (ForStmt or CXXRangeForStmt) of the affected +/// loop of a construct. +static void collectLoopStmts(Stmt *AStmt, MutableArrayRef LoopStmts) { + size_t NumLoops = LoopStmts.size(); + OMPLoopBasedDirective::doForAllLoops( + AStmt, /*TryImperfectlyNestedLoops=*/false, NumLoops, + [LoopStmts](unsigned Cnt, Stmt *CurStmt) { + assert(!LoopStmts[Cnt] && "Loop statement must not yet be assigned"); + LoopStmts[Cnt] = CurStmt; + return false; + }); + assert(!is_contained(LoopStmts, nullptr) && + "Expecting a loop statement for each affected loop"); +} + StmtResult SemaOpenMP::ActOnOpenMPTileDirective(ArrayRef Clauses, Stmt *AStmt, SourceLocation StartLoc, @@ -15126,8 +15218,7 @@ StmtResult SemaOpenMP::ActOnOpenMPTileDirective(ArrayRef Clauses, // Verify and diagnose loop nest. SmallVector LoopHelpers(NumLoops); Stmt *Body = nullptr; - SmallVector, 0>, 4> - OriginalInits; + SmallVector, 4> OriginalInits; if (!checkTransformableLoopNest(OMPD_tile, AStmt, NumLoops, LoopHelpers, Body, OriginalInits)) return StmtError(); @@ -15144,7 +15235,11 @@ StmtResult SemaOpenMP::ActOnOpenMPTileDirective(ArrayRef Clauses, "Expecting loop iteration space dimensionality to match number of " "affected loops"); - SmallVector PreInits; + // Collect all affected loop statements. + SmallVector LoopStmts(NumLoops, nullptr); + collectLoopStmts(AStmt, LoopStmts); + + SmallVector PreInits; CaptureVars CopyTransformer(SemaRef); // Create iteration variables for the generated loops. @@ -15184,20 +15279,9 @@ StmtResult SemaOpenMP::ActOnOpenMPTileDirective(ArrayRef Clauses, &SemaRef.PP.getIdentifierTable().get(TileCntName)); TileIndVars[I] = TileCntDecl; } - for (auto &P : OriginalInits[I]) { - if (auto *D = P.dyn_cast()) - PreInits.push_back(D); - else if (auto *PI = dyn_cast_or_null(P.dyn_cast())) - PreInits.append(PI->decl_begin(), PI->decl_end()); - } - if (auto *PI = cast_or_null(LoopHelper.PreInits)) - PreInits.append(PI->decl_begin(), PI->decl_end()); - // Gather declarations for the data members used as counters. - for (Expr *CounterRef : LoopHelper.Counters) { - auto *CounterDecl = cast(CounterRef)->getDecl(); - if (isa(CounterDecl)) - PreInits.push_back(CounterDecl); - } + + addLoopPreInits(Context, LoopHelper, LoopStmts[I], OriginalInits[I], + PreInits); } // Once the original iteration values are set, append the innermost body. @@ -15246,19 +15330,20 @@ StmtResult SemaOpenMP::ActOnOpenMPTileDirective(ArrayRef Clauses, OMPLoopBasedDirective::HelperExprs &LoopHelper = LoopHelpers[I]; Expr *NumIterations = LoopHelper.NumIterations; auto *OrigCntVar = cast(LoopHelper.Counters[0]); - QualType CntTy = OrigCntVar->getType(); + QualType IVTy = NumIterations->getType(); + Stmt *LoopStmt = LoopStmts[I]; // Commonly used variables. One of the constraints of an AST is that every // node object must appear at most once, hence we define lamdas that create // a new AST node at every use. - auto MakeTileIVRef = [&SemaRef = this->SemaRef, &TileIndVars, I, CntTy, + auto MakeTileIVRef = [&SemaRef = this->SemaRef, &TileIndVars, I, IVTy, OrigCntVar]() { - return buildDeclRefExpr(SemaRef, TileIndVars[I], CntTy, + return buildDeclRefExpr(SemaRef, TileIndVars[I], IVTy, OrigCntVar->getExprLoc()); }; - auto MakeFloorIVRef = [&SemaRef = this->SemaRef, &FloorIndVars, I, CntTy, + auto MakeFloorIVRef = [&SemaRef = this->SemaRef, &FloorIndVars, I, IVTy, OrigCntVar]() { - return buildDeclRefExpr(SemaRef, FloorIndVars[I], CntTy, + return buildDeclRefExpr(SemaRef, FloorIndVars[I], IVTy, OrigCntVar->getExprLoc()); }; @@ -15320,6 +15405,8 @@ StmtResult SemaOpenMP::ActOnOpenMPTileDirective(ArrayRef Clauses, // further into the inner loop. SmallVector BodyParts; BodyParts.append(LoopHelper.Updates.begin(), LoopHelper.Updates.end()); + if (auto *SourceCXXFor = dyn_cast(LoopStmt)) + BodyParts.push_back(SourceCXXFor->getLoopVarStmt()); BodyParts.push_back(Inner); Inner = CompoundStmt::Create(Context, BodyParts, FPOptionsOverride(), Inner->getBeginLoc(), Inner->getEndLoc()); @@ -15334,12 +15421,14 @@ StmtResult SemaOpenMP::ActOnOpenMPTileDirective(ArrayRef Clauses, auto &LoopHelper = LoopHelpers[I]; Expr *NumIterations = LoopHelper.NumIterations; DeclRefExpr *OrigCntVar = cast(LoopHelper.Counters[0]); - QualType CntTy = OrigCntVar->getType(); + QualType IVTy = NumIterations->getType(); - // Commonly used variables. - auto MakeFloorIVRef = [&SemaRef = this->SemaRef, &FloorIndVars, I, CntTy, + // Commonly used variables. One of the constraints of an AST is that every + // node object must appear at most once, hence we define lamdas that create + // a new AST node at every use. + auto MakeFloorIVRef = [&SemaRef = this->SemaRef, &FloorIndVars, I, IVTy, OrigCntVar]() { - return buildDeclRefExpr(SemaRef, FloorIndVars[I], CntTy, + return buildDeclRefExpr(SemaRef, FloorIndVars[I], IVTy, OrigCntVar->getExprLoc()); }; @@ -15405,8 +15494,7 @@ StmtResult SemaOpenMP::ActOnOpenMPUnrollDirective(ArrayRef Clauses, Stmt *Body = nullptr; SmallVector LoopHelpers( NumLoops); - SmallVector, 0>, NumLoops + 1> - OriginalInits; + SmallVector, NumLoops + 1> OriginalInits; if (!checkTransformableLoopNest(OMPD_unroll, AStmt, NumLoops, LoopHelpers, Body, OriginalInits)) return StmtError(); @@ -15418,6 +15506,10 @@ StmtResult SemaOpenMP::ActOnOpenMPUnrollDirective(ArrayRef Clauses, return OMPUnrollDirective::Create(Context, StartLoc, EndLoc, Clauses, AStmt, NumGeneratedLoops, nullptr, nullptr); + assert(LoopHelpers.size() == NumLoops && + "Expecting a single-dimensional loop iteration space"); + assert(OriginalInits.size() == NumLoops && + "Expecting a single-dimensional loop iteration space"); OMPLoopBasedDirective::HelperExprs &LoopHelper = LoopHelpers.front(); if (FullClause) { @@ -15481,24 +15573,13 @@ StmtResult SemaOpenMP::ActOnOpenMPUnrollDirective(ArrayRef Clauses, // of a canonical loop nest where these PreInits are emitted before the // outermost directive. + // Find the loop statement. + Stmt *LoopStmt = nullptr; + collectLoopStmts(AStmt, {LoopStmt}); + // Determine the PreInit declarations. - SmallVector PreInits; - assert(OriginalInits.size() == 1 && - "Expecting a single-dimensional loop iteration space"); - for (auto &P : OriginalInits[0]) { - if (auto *D = P.dyn_cast()) - PreInits.push_back(D); - else if (auto *PI = dyn_cast_or_null(P.dyn_cast())) - PreInits.append(PI->decl_begin(), PI->decl_end()); - } - if (auto *PI = cast_or_null(LoopHelper.PreInits)) - PreInits.append(PI->decl_begin(), PI->decl_end()); - // Gather declarations for the data members used as counters. - for (Expr *CounterRef : LoopHelper.Counters) { - auto *CounterDecl = cast(CounterRef)->getDecl(); - if (isa(CounterDecl)) - PreInits.push_back(CounterDecl); - } + SmallVector PreInits; + addLoopPreInits(Context, LoopHelper, LoopStmt, OriginalInits[0], PreInits); auto *IterationVarRef = cast(LoopHelper.IterationVarRef); QualType IVTy = IterationVarRef->getType(); @@ -15604,6 +15685,8 @@ StmtResult SemaOpenMP::ActOnOpenMPUnrollDirective(ArrayRef Clauses, // Inner For statement. SmallVector InnerBodyStmts; InnerBodyStmts.append(LoopHelper.Updates.begin(), LoopHelper.Updates.end()); + if (auto *CXXRangeFor = dyn_cast(LoopStmt)) + InnerBodyStmts.push_back(CXXRangeFor->getLoopVarStmt()); InnerBodyStmts.push_back(Body); CompoundStmt *InnerBody = CompoundStmt::Create(getASTContext(), InnerBodyStmts, FPOptionsOverride(), diff --git a/clang/test/OpenMP/tile_codegen.cpp b/clang/test/OpenMP/tile_codegen.cpp index 93a3a14133ab..5fd5609b844c 100644 --- a/clang/test/OpenMP/tile_codegen.cpp +++ b/clang/test/OpenMP/tile_codegen.cpp @@ -1,10 +1,10 @@ -// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --function-signature --include-generated-funcs --replace-value-regex "__omp_offloading_[0-9a-z]+_[0-9a-z]+" "reduction_size[.].+[.]" "pl_cond[.].+[.|,]" --prefix-filecheck-ir-name _ +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --include-generated-funcs --replace-value-regex "__omp_offloading_[0-9a-z]+_[0-9a-z]+" "reduction_size[.].+[.]" "pl_cond[.].+[.|,]" --prefix-filecheck-ir-name _ --version 4 // Check code generation -// RUN: %clang_cc1 -verify -triple x86_64-pc-linux-gnu -fclang-abi-compat=latest -fopenmp -emit-llvm %s -o - | FileCheck %s --check-prefix=CHECK1 +// RUN: %clang_cc1 -verify -triple x86_64-pc-linux-gnu -fclang-abi-compat=latest -std=c++20 -fopenmp -emit-llvm %s -o - | FileCheck %s --check-prefix=CHECK1 // Check same results after serialization round-trip -// RUN: %clang_cc1 -verify -triple x86_64-pc-linux-gnu -fclang-abi-compat=latest -fopenmp -emit-pch -o %t %s -// RUN: %clang_cc1 -verify -triple x86_64-pc-linux-gnu -fclang-abi-compat=latest -fopenmp -include-pch %t -emit-llvm %s -o - | FileCheck %s --check-prefix=CHECK2 +// RUN: %clang_cc1 -verify -triple x86_64-pc-linux-gnu -fclang-abi-compat=latest -std=c++20 -fopenmp -emit-pch -o %t %s +// RUN: %clang_cc1 -verify -triple x86_64-pc-linux-gnu -fclang-abi-compat=latest -std=c++20 -fopenmp -include-pch %t -emit-llvm %s -o - | FileCheck %s --check-prefix=CHECK2 // expected-no-diagnostics #ifndef HEADER @@ -91,22 +91,38 @@ extern "C" void foo8(int a) { } +typedef struct { double array[12]; } data_t; +extern "C" void foo9(data_t data) { +#pragma omp tile sizes(5) + for (double v : data.array) + body(v); +} + + +extern "C" void foo10(data_t data) { +#pragma omp tile sizes(5) + for (double c = 42.0; double v : data.array) + body(c, v); +} + + #endif /* HEADER */ -// CHECK1-LABEL: define {{[^@]+}}@body -// CHECK1-SAME: (...) #[[ATTR0:[0-9]+]] { + +// CHECK1-LABEL: define dso_local void @body( +// CHECK1-SAME: ...) #[[ATTR0:[0-9]+]] { // CHECK1-NEXT: entry: // CHECK1-NEXT: ret void // // -// CHECK1-LABEL: define {{[^@]+}}@__cxx_global_var_init -// CHECK1-SAME: () #[[ATTR1:[0-9]+]] section ".text.startup" { +// CHECK1-LABEL: define internal void @__cxx_global_var_init( +// CHECK1-SAME: ) #[[ATTR1:[0-9]+]] section ".text.startup" { // CHECK1-NEXT: entry: // CHECK1-NEXT: call void @_ZN1SC1Ev(ptr noundef nonnull align 4 dereferenceable(4) @s) // CHECK1-NEXT: ret void // // -// CHECK1-LABEL: define {{[^@]+}}@_ZN1SC1Ev -// CHECK1-SAME: (ptr noundef nonnull align 4 dereferenceable(4) [[THIS:%.*]]) unnamed_addr #[[ATTR0]] comdat align 2 { +// CHECK1-LABEL: define linkonce_odr void @_ZN1SC1Ev( +// CHECK1-SAME: ptr noundef nonnull align 4 dereferenceable(4) [[THIS:%.*]]) unnamed_addr #[[ATTR0]] comdat align 2 { // CHECK1-NEXT: entry: // CHECK1-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 8 // CHECK1-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 8 @@ -115,50 +131,52 @@ extern "C" void foo8(int a) { // CHECK1-NEXT: ret void // // -// CHECK1-LABEL: define {{[^@]+}}@_ZN1SC2Ev -// CHECK1-SAME: (ptr noundef nonnull align 4 dereferenceable(4) [[THIS:%.*]]) unnamed_addr #[[ATTR0]] comdat align 2 { +// CHECK1-LABEL: define linkonce_odr void @_ZN1SC2Ev( +// CHECK1-SAME: ptr noundef nonnull align 4 dereferenceable(4) [[THIS:%.*]]) unnamed_addr #[[ATTR0]] comdat align 2 { // CHECK1-NEXT: entry: // CHECK1-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 8 -// CHECK1-NEXT: [[I:%.*]] = alloca ptr, align 8 +// CHECK1-NEXT: [[I2:%.*]] = alloca ptr, align 8 // CHECK1-NEXT: [[DOTFLOOR_0_IV_I:%.*]] = alloca i32, align 4 // CHECK1-NEXT: [[DOTTILE_0_IV_I:%.*]] = alloca i32, align 4 // CHECK1-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 8 // CHECK1-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8 -// CHECK1-NEXT: [[I2:%.*]] = getelementptr inbounds [[STRUCT_S:%.*]], ptr [[THIS1]], i32 0, i32 0 -// CHECK1-NEXT: store ptr [[I2]], ptr [[I]], align 8 +// CHECK1-NEXT: [[I:%.*]] = getelementptr inbounds [[STRUCT_S:%.*]], ptr [[THIS1]], i32 0, i32 0 +// CHECK1-NEXT: store i32 7, ptr [[I]], align 4 +// CHECK1-NEXT: [[I3:%.*]] = getelementptr inbounds [[STRUCT_S]], ptr [[THIS1]], i32 0, i32 0 +// CHECK1-NEXT: store ptr [[I3]], ptr [[I2]], align 8 // CHECK1-NEXT: store i32 0, ptr [[DOTFLOOR_0_IV_I]], align 4 // CHECK1-NEXT: br label [[FOR_COND:%.*]] // CHECK1: for.cond: // CHECK1-NEXT: [[TMP0:%.*]] = load i32, ptr [[DOTFLOOR_0_IV_I]], align 4 // CHECK1-NEXT: [[CMP:%.*]] = icmp slt i32 [[TMP0]], 4 -// CHECK1-NEXT: br i1 [[CMP]], label [[FOR_BODY:%.*]], label [[FOR_END11:%.*]] +// CHECK1-NEXT: br i1 [[CMP]], label [[FOR_BODY:%.*]], label [[FOR_END12:%.*]] // CHECK1: for.body: // CHECK1-NEXT: [[TMP1:%.*]] = load i32, ptr [[DOTFLOOR_0_IV_I]], align 4 // CHECK1-NEXT: store i32 [[TMP1]], ptr [[DOTTILE_0_IV_I]], align 4 -// CHECK1-NEXT: br label [[FOR_COND3:%.*]] -// CHECK1: for.cond3: +// CHECK1-NEXT: br label [[FOR_COND4:%.*]] +// CHECK1: for.cond4: // CHECK1-NEXT: [[TMP2:%.*]] = load i32, ptr [[DOTTILE_0_IV_I]], align 4 // CHECK1-NEXT: [[TMP3:%.*]] = load i32, ptr [[DOTFLOOR_0_IV_I]], align 4 // CHECK1-NEXT: [[ADD:%.*]] = add nsw i32 [[TMP3]], 5 -// CHECK1-NEXT: [[CMP4:%.*]] = icmp slt i32 4, [[ADD]] -// CHECK1-NEXT: br i1 [[CMP4]], label [[COND_TRUE:%.*]], label [[COND_FALSE:%.*]] +// CHECK1-NEXT: [[CMP5:%.*]] = icmp slt i32 4, [[ADD]] +// CHECK1-NEXT: br i1 [[CMP5]], label [[COND_TRUE:%.*]], label [[COND_FALSE:%.*]] // CHECK1: cond.true: // CHECK1-NEXT: br label [[COND_END:%.*]] // CHECK1: cond.false: // CHECK1-NEXT: [[TMP4:%.*]] = load i32, ptr [[DOTFLOOR_0_IV_I]], align 4 -// CHECK1-NEXT: [[ADD5:%.*]] = add nsw i32 [[TMP4]], 5 +// CHECK1-NEXT: [[ADD6:%.*]] = add nsw i32 [[TMP4]], 5 // CHECK1-NEXT: br label [[COND_END]] // CHECK1: cond.end: -// CHECK1-NEXT: [[COND:%.*]] = phi i32 [ 4, [[COND_TRUE]] ], [ [[ADD5]], [[COND_FALSE]] ] -// CHECK1-NEXT: [[CMP6:%.*]] = icmp slt i32 [[TMP2]], [[COND]] -// CHECK1-NEXT: br i1 [[CMP6]], label [[FOR_BODY7:%.*]], label [[FOR_END:%.*]] -// CHECK1: for.body7: +// CHECK1-NEXT: [[COND:%.*]] = phi i32 [ 4, [[COND_TRUE]] ], [ [[ADD6]], [[COND_FALSE]] ] +// CHECK1-NEXT: [[CMP7:%.*]] = icmp slt i32 [[TMP2]], [[COND]] +// CHECK1-NEXT: br i1 [[CMP7]], label [[FOR_BODY8:%.*]], label [[FOR_END:%.*]] +// CHECK1: for.body8: // CHECK1-NEXT: [[TMP5:%.*]] = load i32, ptr [[DOTTILE_0_IV_I]], align 4 // CHECK1-NEXT: [[MUL:%.*]] = mul nsw i32 [[TMP5]], 3 -// CHECK1-NEXT: [[ADD8:%.*]] = add nsw i32 7, [[MUL]] -// CHECK1-NEXT: [[TMP6:%.*]] = load ptr, ptr [[I]], align 8 -// CHECK1-NEXT: store i32 [[ADD8]], ptr [[TMP6]], align 4 -// CHECK1-NEXT: [[TMP7:%.*]] = load ptr, ptr [[I]], align 8 +// CHECK1-NEXT: [[ADD9:%.*]] = add nsw i32 7, [[MUL]] +// CHECK1-NEXT: [[TMP6:%.*]] = load ptr, ptr [[I2]], align 8 +// CHECK1-NEXT: store i32 [[ADD9]], ptr [[TMP6]], align 4 +// CHECK1-NEXT: [[TMP7:%.*]] = load ptr, ptr [[I2]], align 8 // CHECK1-NEXT: [[TMP8:%.*]] = load i32, ptr [[TMP7]], align 4 // CHECK1-NEXT: call void (...) @body(i32 noundef [[TMP8]]) // CHECK1-NEXT: br label [[FOR_INC:%.*]] @@ -166,20 +184,20 @@ extern "C" void foo8(int a) { // CHECK1-NEXT: [[TMP9:%.*]] = load i32, ptr [[DOTTILE_0_IV_I]], align 4 // CHECK1-NEXT: [[INC:%.*]] = add nsw i32 [[TMP9]], 1 // CHECK1-NEXT: store i32 [[INC]], ptr [[DOTTILE_0_IV_I]], align 4 -// CHECK1-NEXT: br label [[FOR_COND3]], !llvm.loop [[LOOP3:![0-9]+]] +// CHECK1-NEXT: br label [[FOR_COND4]], !llvm.loop [[LOOP3:![0-9]+]] // CHECK1: for.end: -// CHECK1-NEXT: br label [[FOR_INC9:%.*]] -// CHECK1: for.inc9: +// CHECK1-NEXT: br label [[FOR_INC10:%.*]] +// CHECK1: for.inc10: // CHECK1-NEXT: [[TMP10:%.*]] = load i32, ptr [[DOTFLOOR_0_IV_I]], align 4 -// CHECK1-NEXT: [[ADD10:%.*]] = add nsw i32 [[TMP10]], 5 -// CHECK1-NEXT: store i32 [[ADD10]], ptr [[DOTFLOOR_0_IV_I]], align 4 +// CHECK1-NEXT: [[ADD11:%.*]] = add nsw i32 [[TMP10]], 5 +// CHECK1-NEXT: store i32 [[ADD11]], ptr [[DOTFLOOR_0_IV_I]], align 4 // CHECK1-NEXT: br label [[FOR_COND]], !llvm.loop [[LOOP5:![0-9]+]] -// CHECK1: for.end11: +// CHECK1: for.end12: // CHECK1-NEXT: ret void // // -// CHECK1-LABEL: define {{[^@]+}}@foo1 -// CHECK1-SAME: (i32 noundef [[START:%.*]], i32 noundef [[END:%.*]], i32 noundef [[STEP:%.*]]) #[[ATTR0]] { +// CHECK1-LABEL: define dso_local void @foo1( +// CHECK1-SAME: i32 noundef [[START:%.*]], i32 noundef [[END:%.*]], i32 noundef [[STEP:%.*]]) #[[ATTR0]] { // CHECK1-NEXT: entry: // CHECK1-NEXT: [[START_ADDR:%.*]] = alloca i32, align 4 // CHECK1-NEXT: [[END_ADDR:%.*]] = alloca i32, align 4 @@ -195,81 +213,83 @@ extern "C" void foo8(int a) { // CHECK1-NEXT: store i32 [[END]], ptr [[END_ADDR]], align 4 // CHECK1-NEXT: store i32 [[STEP]], ptr [[STEP_ADDR]], align 4 // CHECK1-NEXT: [[TMP0:%.*]] = load i32, ptr [[START_ADDR]], align 4 -// CHECK1-NEXT: store i32 [[TMP0]], ptr [[DOTCAPTURE_EXPR_]], align 4 -// CHECK1-NEXT: [[TMP1:%.*]] = load i32, ptr [[END_ADDR]], align 4 -// CHECK1-NEXT: store i32 [[TMP1]], ptr [[DOTCAPTURE_EXPR_1]], align 4 -// CHECK1-NEXT: [[TMP2:%.*]] = load i32, ptr [[STEP_ADDR]], align 4 -// CHECK1-NEXT: store i32 [[TMP2]], ptr [[DOTNEW_STEP]], align 4 -// CHECK1-NEXT: [[TMP3:%.*]] = load i32, ptr [[DOTCAPTURE_EXPR_1]], align 4 -// CHECK1-NEXT: [[TMP4:%.*]] = load i32, ptr [[DOTCAPTURE_EXPR_]], align 4 -// CHECK1-NEXT: [[SUB:%.*]] = sub i32 [[TMP3]], [[TMP4]] +// CHECK1-NEXT: store i32 [[TMP0]], ptr [[I]], align 4 +// CHECK1-NEXT: [[TMP1:%.*]] = load i32, ptr [[START_ADDR]], align 4 +// CHECK1-NEXT: store i32 [[TMP1]], ptr [[DOTCAPTURE_EXPR_]], align 4 +// CHECK1-NEXT: [[TMP2:%.*]] = load i32, ptr [[END_ADDR]], align 4 +// CHECK1-NEXT: store i32 [[TMP2]], ptr [[DOTCAPTURE_EXPR_1]], align 4 +// CHECK1-NEXT: [[TMP3:%.*]] = load i32, ptr [[STEP_ADDR]], align 4 +// CHECK1-NEXT: store i32 [[TMP3]], ptr [[DOTNEW_STEP]], align 4 +// CHECK1-NEXT: [[TMP4:%.*]] = load i32, ptr [[DOTCAPTURE_EXPR_1]], align 4 +// CHECK1-NEXT: [[TMP5:%.*]] = load i32, ptr [[DOTCAPTURE_EXPR_]], align 4 +// CHECK1-NEXT: [[SUB:%.*]] = sub i32 [[TMP4]], [[TMP5]] // CHECK1-NEXT: [[SUB3:%.*]] = sub i32 [[SUB]], 1 -// CHECK1-NEXT: [[TMP5:%.*]] = load i32, ptr [[DOTNEW_STEP]], align 4 -// CHECK1-NEXT: [[ADD:%.*]] = add i32 [[SUB3]], [[TMP5]] // CHECK1-NEXT: [[TMP6:%.*]] = load i32, ptr [[DOTNEW_STEP]], align 4 -// CHECK1-NEXT: [[DIV:%.*]] = udiv i32 [[ADD]], [[TMP6]] +// CHECK1-NEXT: [[ADD:%.*]] = add i32 [[SUB3]], [[TMP6]] +// CHECK1-NEXT: [[TMP7:%.*]] = load i32, ptr [[DOTNEW_STEP]], align 4 +// CHECK1-NEXT: [[DIV:%.*]] = udiv i32 [[ADD]], [[TMP7]] // CHECK1-NEXT: [[SUB4:%.*]] = sub i32 [[DIV]], 1 // CHECK1-NEXT: store i32 [[SUB4]], ptr [[DOTCAPTURE_EXPR_2]], align 4 // CHECK1-NEXT: store i32 0, ptr [[DOTFLOOR_0_IV_I]], align 4 // CHECK1-NEXT: br label [[FOR_COND:%.*]] // CHECK1: for.cond: -// CHECK1-NEXT: [[TMP7:%.*]] = load i32, ptr [[DOTFLOOR_0_IV_I]], align 4 -// CHECK1-NEXT: [[TMP8:%.*]] = load i32, ptr [[DOTCAPTURE_EXPR_2]], align 4 -// CHECK1-NEXT: [[ADD5:%.*]] = add i32 [[TMP8]], 1 -// CHECK1-NEXT: [[CMP:%.*]] = icmp ult i32 [[TMP7]], [[ADD5]] +// CHECK1-NEXT: [[TMP8:%.*]] = load i32, ptr [[DOTFLOOR_0_IV_I]], align 4 +// CHECK1-NEXT: [[TMP9:%.*]] = load i32, ptr [[DOTCAPTURE_EXPR_2]], align 4 +// CHECK1-NEXT: [[ADD5:%.*]] = add i32 [[TMP9]], 1 +// CHECK1-NEXT: [[CMP:%.*]] = icmp ult i32 [[TMP8]], [[ADD5]] // CHECK1-NEXT: br i1 [[CMP]], label [[FOR_BODY:%.*]], label [[FOR_END17:%.*]] // CHECK1: for.body: -// CHECK1-NEXT: [[TMP9:%.*]] = load i32, ptr [[DOTFLOOR_0_IV_I]], align 4 -// CHECK1-NEXT: store i32 [[TMP9]], ptr [[DOTTILE_0_IV_I]], align 4 +// CHECK1-NEXT: [[TMP10:%.*]] = load i32, ptr [[DOTFLOOR_0_IV_I]], align 4 +// CHECK1-NEXT: store i32 [[TMP10]], ptr [[DOTTILE_0_IV_I]], align 4 // CHECK1-NEXT: br label [[FOR_COND6:%.*]] // CHECK1: for.cond6: -// CHECK1-NEXT: [[TMP10:%.*]] = load i32, ptr [[DOTTILE_0_IV_I]], align 4 -// CHECK1-NEXT: [[TMP11:%.*]] = load i32, ptr [[DOTCAPTURE_EXPR_2]], align 4 -// CHECK1-NEXT: [[ADD7:%.*]] = add i32 [[TMP11]], 1 -// CHECK1-NEXT: [[TMP12:%.*]] = load i32, ptr [[DOTFLOOR_0_IV_I]], align 4 -// CHECK1-NEXT: [[ADD8:%.*]] = add nsw i32 [[TMP12]], 5 +// CHECK1-NEXT: [[TMP11:%.*]] = load i32, ptr [[DOTTILE_0_IV_I]], align 4 +// CHECK1-NEXT: [[TMP12:%.*]] = load i32, ptr [[DOTCAPTURE_EXPR_2]], align 4 +// CHECK1-NEXT: [[ADD7:%.*]] = add i32 [[TMP12]], 1 +// CHECK1-NEXT: [[TMP13:%.*]] = load i32, ptr [[DOTFLOOR_0_IV_I]], align 4 +// CHECK1-NEXT: [[ADD8:%.*]] = add i32 [[TMP13]], 5 // CHECK1-NEXT: [[CMP9:%.*]] = icmp ult i32 [[ADD7]], [[ADD8]] // CHECK1-NEXT: br i1 [[CMP9]], label [[COND_TRUE:%.*]], label [[COND_FALSE:%.*]] // CHECK1: cond.true: -// CHECK1-NEXT: [[TMP13:%.*]] = load i32, ptr [[DOTCAPTURE_EXPR_2]], align 4 -// CHECK1-NEXT: [[ADD10:%.*]] = add i32 [[TMP13]], 1 +// CHECK1-NEXT: [[TMP14:%.*]] = load i32, ptr [[DOTCAPTURE_EXPR_2]], align 4 +// CHECK1-NEXT: [[ADD10:%.*]] = add i32 [[TMP14]], 1 // CHECK1-NEXT: br label [[COND_END:%.*]] // CHECK1: cond.false: -// CHECK1-NEXT: [[TMP14:%.*]] = load i32, ptr [[DOTFLOOR_0_IV_I]], align 4 -// CHECK1-NEXT: [[ADD11:%.*]] = add nsw i32 [[TMP14]], 5 +// CHECK1-NEXT: [[TMP15:%.*]] = load i32, ptr [[DOTFLOOR_0_IV_I]], align 4 +// CHECK1-NEXT: [[ADD11:%.*]] = add i32 [[TMP15]], 5 // CHECK1-NEXT: br label [[COND_END]] // CHECK1: cond.end: // CHECK1-NEXT: [[COND:%.*]] = phi i32 [ [[ADD10]], [[COND_TRUE]] ], [ [[ADD11]], [[COND_FALSE]] ] -// CHECK1-NEXT: [[CMP12:%.*]] = icmp ult i32 [[TMP10]], [[COND]] +// CHECK1-NEXT: [[CMP12:%.*]] = icmp ult i32 [[TMP11]], [[COND]] // CHECK1-NEXT: br i1 [[CMP12]], label [[FOR_BODY13:%.*]], label [[FOR_END:%.*]] // CHECK1: for.body13: -// CHECK1-NEXT: [[TMP15:%.*]] = load i32, ptr [[DOTCAPTURE_EXPR_]], align 4 -// CHECK1-NEXT: [[TMP16:%.*]] = load i32, ptr [[DOTTILE_0_IV_I]], align 4 -// CHECK1-NEXT: [[TMP17:%.*]] = load i32, ptr [[DOTNEW_STEP]], align 4 -// CHECK1-NEXT: [[MUL:%.*]] = mul i32 [[TMP16]], [[TMP17]] -// CHECK1-NEXT: [[ADD14:%.*]] = add i32 [[TMP15]], [[MUL]] +// CHECK1-NEXT: [[TMP16:%.*]] = load i32, ptr [[DOTCAPTURE_EXPR_]], align 4 +// CHECK1-NEXT: [[TMP17:%.*]] = load i32, ptr [[DOTTILE_0_IV_I]], align 4 +// CHECK1-NEXT: [[TMP18:%.*]] = load i32, ptr [[DOTNEW_STEP]], align 4 +// CHECK1-NEXT: [[MUL:%.*]] = mul i32 [[TMP17]], [[TMP18]] +// CHECK1-NEXT: [[ADD14:%.*]] = add i32 [[TMP16]], [[MUL]] // CHECK1-NEXT: store i32 [[ADD14]], ptr [[I]], align 4 -// CHECK1-NEXT: [[TMP18:%.*]] = load i32, ptr [[I]], align 4 -// CHECK1-NEXT: call void (...) @body(i32 noundef [[TMP18]]) +// CHECK1-NEXT: [[TMP19:%.*]] = load i32, ptr [[I]], align 4 +// CHECK1-NEXT: call void (...) @body(i32 noundef [[TMP19]]) // CHECK1-NEXT: br label [[FOR_INC:%.*]] // CHECK1: for.inc: -// CHECK1-NEXT: [[TMP19:%.*]] = load i32, ptr [[DOTTILE_0_IV_I]], align 4 -// CHECK1-NEXT: [[INC:%.*]] = add nsw i32 [[TMP19]], 1 +// CHECK1-NEXT: [[TMP20:%.*]] = load i32, ptr [[DOTTILE_0_IV_I]], align 4 +// CHECK1-NEXT: [[INC:%.*]] = add i32 [[TMP20]], 1 // CHECK1-NEXT: store i32 [[INC]], ptr [[DOTTILE_0_IV_I]], align 4 // CHECK1-NEXT: br label [[FOR_COND6]], !llvm.loop [[LOOP6:![0-9]+]] // CHECK1: for.end: // CHECK1-NEXT: br label [[FOR_INC15:%.*]] // CHECK1: for.inc15: -// CHECK1-NEXT: [[TMP20:%.*]] = load i32, ptr [[DOTFLOOR_0_IV_I]], align 4 -// CHECK1-NEXT: [[ADD16:%.*]] = add nsw i32 [[TMP20]], 5 +// CHECK1-NEXT: [[TMP21:%.*]] = load i32, ptr [[DOTFLOOR_0_IV_I]], align 4 +// CHECK1-NEXT: [[ADD16:%.*]] = add i32 [[TMP21]], 5 // CHECK1-NEXT: store i32 [[ADD16]], ptr [[DOTFLOOR_0_IV_I]], align 4 // CHECK1-NEXT: br label [[FOR_COND]], !llvm.loop [[LOOP7:![0-9]+]] // CHECK1: for.end17: // CHECK1-NEXT: ret void // // -// CHECK1-LABEL: define {{[^@]+}}@foo2 -// CHECK1-SAME: (i32 noundef [[START:%.*]], i32 noundef [[END:%.*]], i32 noundef [[STEP:%.*]]) #[[ATTR0]] { +// CHECK1-LABEL: define dso_local void @foo2( +// CHECK1-SAME: i32 noundef [[START:%.*]], i32 noundef [[END:%.*]], i32 noundef [[STEP:%.*]]) #[[ATTR0]] { // CHECK1-NEXT: entry: // CHECK1-NEXT: [[START_ADDR:%.*]] = alloca i32, align 4 // CHECK1-NEXT: [[END_ADDR:%.*]] = alloca i32, align 4 @@ -381,8 +401,8 @@ extern "C" void foo8(int a) { // CHECK1-NEXT: ret void // // -// CHECK1-LABEL: define {{[^@]+}}@foo3 -// CHECK1-SAME: () #[[ATTR0]] { +// CHECK1-LABEL: define dso_local void @foo3( +// CHECK1-SAME: ) #[[ATTR0]] { // CHECK1-NEXT: entry: // CHECK1-NEXT: [[DOTOMP_IV:%.*]] = alloca i32, align 4 // CHECK1-NEXT: [[TMP:%.*]] = alloca i32, align 4 @@ -523,8 +543,8 @@ extern "C" void foo8(int a) { // CHECK1-NEXT: ret void // // -// CHECK1-LABEL: define {{[^@]+}}@foo4 -// CHECK1-SAME: () #[[ATTR0]] { +// CHECK1-LABEL: define dso_local void @foo4( +// CHECK1-SAME: ) #[[ATTR0]] { // CHECK1-NEXT: entry: // CHECK1-NEXT: [[DOTOMP_IV:%.*]] = alloca i32, align 4 // CHECK1-NEXT: [[TMP:%.*]] = alloca i32, align 4 @@ -676,8 +696,8 @@ extern "C" void foo8(int a) { // CHECK1-NEXT: ret void // // -// CHECK1-LABEL: define {{[^@]+}}@foo5 -// CHECK1-SAME: () #[[ATTR0]] { +// CHECK1-LABEL: define dso_local void @foo5( +// CHECK1-SAME: ) #[[ATTR0]] { // CHECK1-NEXT: entry: // CHECK1-NEXT: [[DOTOMP_IV:%.*]] = alloca i64, align 8 // CHECK1-NEXT: [[TMP:%.*]] = alloca i32, align 4 @@ -885,15 +905,15 @@ extern "C" void foo8(int a) { // CHECK1-NEXT: ret void // // -// CHECK1-LABEL: define {{[^@]+}}@foo6 -// CHECK1-SAME: () #[[ATTR0]] { +// CHECK1-LABEL: define dso_local void @foo6( +// CHECK1-SAME: ) #[[ATTR0]] { // CHECK1-NEXT: entry: // CHECK1-NEXT: call void (ptr, i32, ptr, ...) @__kmpc_fork_call(ptr @[[GLOB2]], i32 0, ptr @foo6.omp_outlined) // CHECK1-NEXT: ret void // // -// CHECK1-LABEL: define {{[^@]+}}@foo6.omp_outlined -// CHECK1-SAME: (ptr noalias noundef [[DOTGLOBAL_TID_:%.*]], ptr noalias noundef [[DOTBOUND_TID_:%.*]]) #[[ATTR4:[0-9]+]] { +// CHECK1-LABEL: define internal void @foo6.omp_outlined( +// CHECK1-SAME: ptr noalias noundef [[DOTGLOBAL_TID_:%.*]], ptr noalias noundef [[DOTBOUND_TID_:%.*]]) #[[ATTR4:[0-9]+]] { // CHECK1-NEXT: entry: // CHECK1-NEXT: [[DOTGLOBAL_TID__ADDR:%.*]] = alloca ptr, align 8 // CHECK1-NEXT: [[DOTBOUND_TID__ADDR:%.*]] = alloca ptr, align 8 @@ -988,15 +1008,15 @@ extern "C" void foo8(int a) { // CHECK1-NEXT: ret void // // -// CHECK1-LABEL: define {{[^@]+}}@tfoo7 -// CHECK1-SAME: () #[[ATTR0]] { +// CHECK1-LABEL: define dso_local void @tfoo7( +// CHECK1-SAME: ) #[[ATTR0]] { // CHECK1-NEXT: entry: // CHECK1-NEXT: call void @_Z4foo7IiTnT_Li3ETnS0_Li5EEvS0_S0_(i32 noundef 0, i32 noundef 42) // CHECK1-NEXT: ret void // // -// CHECK1-LABEL: define {{[^@]+}}@_Z4foo7IiTnT_Li3ETnS0_Li5EEvS0_S0_ -// CHECK1-SAME: (i32 noundef [[START:%.*]], i32 noundef [[END:%.*]]) #[[ATTR0]] comdat { +// CHECK1-LABEL: define linkonce_odr void @_Z4foo7IiTnT_Li3ETnS0_Li5EEvS0_S0_( +// CHECK1-SAME: i32 noundef [[START:%.*]], i32 noundef [[END:%.*]]) #[[ATTR0]] comdat { // CHECK1-NEXT: entry: // CHECK1-NEXT: [[START_ADDR:%.*]] = alloca i32, align 4 // CHECK1-NEXT: [[END_ADDR:%.*]] = alloca i32, align 4 @@ -1039,7 +1059,7 @@ extern "C" void foo8(int a) { // CHECK1-NEXT: [[TMP9:%.*]] = load i32, ptr [[DOTCAPTURE_EXPR_2]], align 4 // CHECK1-NEXT: [[ADD7:%.*]] = add i32 [[TMP9]], 1 // CHECK1-NEXT: [[TMP10:%.*]] = load i32, ptr [[DOTFLOOR_0_IV_I]], align 4 -// CHECK1-NEXT: [[ADD8:%.*]] = add nsw i32 [[TMP10]], 5 +// CHECK1-NEXT: [[ADD8:%.*]] = add i32 [[TMP10]], 5 // CHECK1-NEXT: [[CMP9:%.*]] = icmp ult i32 [[ADD7]], [[ADD8]] // CHECK1-NEXT: br i1 [[CMP9]], label [[COND_TRUE:%.*]], label [[COND_FALSE:%.*]] // CHECK1: cond.true: @@ -1048,7 +1068,7 @@ extern "C" void foo8(int a) { // CHECK1-NEXT: br label [[COND_END:%.*]] // CHECK1: cond.false: // CHECK1-NEXT: [[TMP12:%.*]] = load i32, ptr [[DOTFLOOR_0_IV_I]], align 4 -// CHECK1-NEXT: [[ADD11:%.*]] = add nsw i32 [[TMP12]], 5 +// CHECK1-NEXT: [[ADD11:%.*]] = add i32 [[TMP12]], 5 // CHECK1-NEXT: br label [[COND_END]] // CHECK1: cond.end: // CHECK1-NEXT: [[COND:%.*]] = phi i32 [ [[ADD10]], [[COND_TRUE]] ], [ [[ADD11]], [[COND_FALSE]] ] @@ -1065,22 +1085,22 @@ extern "C" void foo8(int a) { // CHECK1-NEXT: br label [[FOR_INC:%.*]] // CHECK1: for.inc: // CHECK1-NEXT: [[TMP16:%.*]] = load i32, ptr [[DOTTILE_0_IV_I]], align 4 -// CHECK1-NEXT: [[INC:%.*]] = add nsw i32 [[TMP16]], 1 +// CHECK1-NEXT: [[INC:%.*]] = add i32 [[TMP16]], 1 // CHECK1-NEXT: store i32 [[INC]], ptr [[DOTTILE_0_IV_I]], align 4 // CHECK1-NEXT: br label [[FOR_COND6]], !llvm.loop [[LOOP21:![0-9]+]] // CHECK1: for.end: // CHECK1-NEXT: br label [[FOR_INC15:%.*]] // CHECK1: for.inc15: // CHECK1-NEXT: [[TMP17:%.*]] = load i32, ptr [[DOTFLOOR_0_IV_I]], align 4 -// CHECK1-NEXT: [[ADD16:%.*]] = add nsw i32 [[TMP17]], 5 +// CHECK1-NEXT: [[ADD16:%.*]] = add i32 [[TMP17]], 5 // CHECK1-NEXT: store i32 [[ADD16]], ptr [[DOTFLOOR_0_IV_I]], align 4 // CHECK1-NEXT: br label [[FOR_COND]], !llvm.loop [[LOOP22:![0-9]+]] // CHECK1: for.end17: // CHECK1-NEXT: ret void // // -// CHECK1-LABEL: define {{[^@]+}}@foo8 -// CHECK1-SAME: (i32 noundef [[A:%.*]]) #[[ATTR0]] { +// CHECK1-LABEL: define dso_local void @foo8( +// CHECK1-SAME: i32 noundef [[A:%.*]]) #[[ATTR0]] { // CHECK1-NEXT: entry: // CHECK1-NEXT: [[A_ADDR:%.*]] = alloca i32, align 4 // CHECK1-NEXT: [[I:%.*]] = alloca i32, align 4 @@ -1168,22 +1188,219 @@ extern "C" void foo8(int a) { // CHECK1-NEXT: ret void // // -// CHECK1-LABEL: define {{[^@]+}}@_GLOBAL__sub_I_tile_codegen.cpp -// CHECK1-SAME: () #[[ATTR1]] section ".text.startup" { +// CHECK1-LABEL: define dso_local void @foo9( +// CHECK1-SAME: ptr noundef byval([[STRUCT_DATA_T:%.*]]) align 8 [[DATA:%.*]]) #[[ATTR0]] { +// CHECK1-NEXT: entry: +// CHECK1-NEXT: [[__RANGE2:%.*]] = alloca ptr, align 8 +// CHECK1-NEXT: [[__END2:%.*]] = alloca ptr, align 8 +// CHECK1-NEXT: [[__BEGIN2:%.*]] = alloca ptr, align 8 +// CHECK1-NEXT: [[DOTCAPTURE_EXPR_:%.*]] = alloca ptr, align 8 +// CHECK1-NEXT: [[DOTCAPTURE_EXPR_3:%.*]] = alloca ptr, align 8 +// CHECK1-NEXT: [[DOTCAPTURE_EXPR_4:%.*]] = alloca i64, align 8 +// CHECK1-NEXT: [[DOTFLOOR_0_IV___BEGIN2:%.*]] = alloca i64, align 8 +// CHECK1-NEXT: [[DOTTILE_0_IV___BEGIN2:%.*]] = alloca i64, align 8 +// CHECK1-NEXT: [[V:%.*]] = alloca double, align 8 +// CHECK1-NEXT: [[ARRAY:%.*]] = getelementptr inbounds [[STRUCT_DATA_T]], ptr [[DATA]], i32 0, i32 0 +// CHECK1-NEXT: store ptr [[ARRAY]], ptr [[__RANGE2]], align 8 +// CHECK1-NEXT: [[TMP0:%.*]] = load ptr, ptr [[__RANGE2]], align 8 +// CHECK1-NEXT: [[ARRAYDECAY:%.*]] = getelementptr inbounds [12 x double], ptr [[TMP0]], i64 0, i64 0 +// CHECK1-NEXT: [[ADD_PTR:%.*]] = getelementptr inbounds double, ptr [[ARRAYDECAY]], i64 12 +// CHECK1-NEXT: store ptr [[ADD_PTR]], ptr [[__END2]], align 8 +// CHECK1-NEXT: [[TMP1:%.*]] = load ptr, ptr [[__RANGE2]], align 8 +// CHECK1-NEXT: [[ARRAYDECAY1:%.*]] = getelementptr inbounds [12 x double], ptr [[TMP1]], i64 0, i64 0 +// CHECK1-NEXT: store ptr [[ARRAYDECAY1]], ptr [[__BEGIN2]], align 8 +// CHECK1-NEXT: [[TMP2:%.*]] = load ptr, ptr [[__RANGE2]], align 8 +// CHECK1-NEXT: [[ARRAYDECAY2:%.*]] = getelementptr inbounds [12 x double], ptr [[TMP2]], i64 0, i64 0 +// CHECK1-NEXT: store ptr [[ARRAYDECAY2]], ptr [[DOTCAPTURE_EXPR_]], align 8 +// CHECK1-NEXT: [[TMP3:%.*]] = load ptr, ptr [[__END2]], align 8 +// CHECK1-NEXT: store ptr [[TMP3]], ptr [[DOTCAPTURE_EXPR_3]], align 8 +// CHECK1-NEXT: [[TMP4:%.*]] = load ptr, ptr [[DOTCAPTURE_EXPR_3]], align 8 +// CHECK1-NEXT: [[TMP5:%.*]] = load ptr, ptr [[DOTCAPTURE_EXPR_]], align 8 +// CHECK1-NEXT: [[SUB_PTR_LHS_CAST:%.*]] = ptrtoint ptr [[TMP4]] to i64 +// CHECK1-NEXT: [[SUB_PTR_RHS_CAST:%.*]] = ptrtoint ptr [[TMP5]] to i64 +// CHECK1-NEXT: [[SUB_PTR_SUB:%.*]] = sub i64 [[SUB_PTR_LHS_CAST]], [[SUB_PTR_RHS_CAST]] +// CHECK1-NEXT: [[SUB_PTR_DIV:%.*]] = sdiv exact i64 [[SUB_PTR_SUB]], 8 +// CHECK1-NEXT: [[SUB:%.*]] = sub nsw i64 [[SUB_PTR_DIV]], 1 +// CHECK1-NEXT: [[ADD:%.*]] = add nsw i64 [[SUB]], 1 +// CHECK1-NEXT: [[DIV:%.*]] = sdiv i64 [[ADD]], 1 +// CHECK1-NEXT: [[SUB5:%.*]] = sub nsw i64 [[DIV]], 1 +// CHECK1-NEXT: store i64 [[SUB5]], ptr [[DOTCAPTURE_EXPR_4]], align 8 +// CHECK1-NEXT: store i64 0, ptr [[DOTFLOOR_0_IV___BEGIN2]], align 8 +// CHECK1-NEXT: br label [[FOR_COND:%.*]] +// CHECK1: for.cond: +// CHECK1-NEXT: [[TMP6:%.*]] = load i64, ptr [[DOTFLOOR_0_IV___BEGIN2]], align 8 +// CHECK1-NEXT: [[TMP7:%.*]] = load i64, ptr [[DOTCAPTURE_EXPR_4]], align 8 +// CHECK1-NEXT: [[ADD6:%.*]] = add nsw i64 [[TMP7]], 1 +// CHECK1-NEXT: [[CMP:%.*]] = icmp slt i64 [[TMP6]], [[ADD6]] +// CHECK1-NEXT: br i1 [[CMP]], label [[FOR_BODY:%.*]], label [[FOR_END18:%.*]] +// CHECK1: for.body: +// CHECK1-NEXT: [[TMP8:%.*]] = load i64, ptr [[DOTFLOOR_0_IV___BEGIN2]], align 8 +// CHECK1-NEXT: store i64 [[TMP8]], ptr [[DOTTILE_0_IV___BEGIN2]], align 8 +// CHECK1-NEXT: br label [[FOR_COND7:%.*]] +// CHECK1: for.cond7: +// CHECK1-NEXT: [[TMP9:%.*]] = load i64, ptr [[DOTTILE_0_IV___BEGIN2]], align 8 +// CHECK1-NEXT: [[TMP10:%.*]] = load i64, ptr [[DOTCAPTURE_EXPR_4]], align 8 +// CHECK1-NEXT: [[ADD8:%.*]] = add nsw i64 [[TMP10]], 1 +// CHECK1-NEXT: [[TMP11:%.*]] = load i64, ptr [[DOTFLOOR_0_IV___BEGIN2]], align 8 +// CHECK1-NEXT: [[ADD9:%.*]] = add nsw i64 [[TMP11]], 5 +// CHECK1-NEXT: [[CMP10:%.*]] = icmp slt i64 [[ADD8]], [[ADD9]] +// CHECK1-NEXT: br i1 [[CMP10]], label [[COND_TRUE:%.*]], label [[COND_FALSE:%.*]] +// CHECK1: cond.true: +// CHECK1-NEXT: [[TMP12:%.*]] = load i64, ptr [[DOTCAPTURE_EXPR_4]], align 8 +// CHECK1-NEXT: [[ADD11:%.*]] = add nsw i64 [[TMP12]], 1 +// CHECK1-NEXT: br label [[COND_END:%.*]] +// CHECK1: cond.false: +// CHECK1-NEXT: [[TMP13:%.*]] = load i64, ptr [[DOTFLOOR_0_IV___BEGIN2]], align 8 +// CHECK1-NEXT: [[ADD12:%.*]] = add nsw i64 [[TMP13]], 5 +// CHECK1-NEXT: br label [[COND_END]] +// CHECK1: cond.end: +// CHECK1-NEXT: [[COND:%.*]] = phi i64 [ [[ADD11]], [[COND_TRUE]] ], [ [[ADD12]], [[COND_FALSE]] ] +// CHECK1-NEXT: [[CMP13:%.*]] = icmp slt i64 [[TMP9]], [[COND]] +// CHECK1-NEXT: br i1 [[CMP13]], label [[FOR_BODY14:%.*]], label [[FOR_END:%.*]] +// CHECK1: for.body14: +// CHECK1-NEXT: [[TMP14:%.*]] = load ptr, ptr [[DOTCAPTURE_EXPR_]], align 8 +// CHECK1-NEXT: [[TMP15:%.*]] = load i64, ptr [[DOTTILE_0_IV___BEGIN2]], align 8 +// CHECK1-NEXT: [[MUL:%.*]] = mul nsw i64 [[TMP15]], 1 +// CHECK1-NEXT: [[ADD_PTR15:%.*]] = getelementptr inbounds double, ptr [[TMP14]], i64 [[MUL]] +// CHECK1-NEXT: store ptr [[ADD_PTR15]], ptr [[__BEGIN2]], align 8 +// CHECK1-NEXT: [[TMP16:%.*]] = load ptr, ptr [[__BEGIN2]], align 8 +// CHECK1-NEXT: [[TMP17:%.*]] = load double, ptr [[TMP16]], align 8 +// CHECK1-NEXT: store double [[TMP17]], ptr [[V]], align 8 +// CHECK1-NEXT: [[TMP18:%.*]] = load double, ptr [[V]], align 8 +// CHECK1-NEXT: call void (...) @body(double noundef [[TMP18]]) +// CHECK1-NEXT: br label [[FOR_INC:%.*]] +// CHECK1: for.inc: +// CHECK1-NEXT: [[TMP19:%.*]] = load i64, ptr [[DOTTILE_0_IV___BEGIN2]], align 8 +// CHECK1-NEXT: [[INC:%.*]] = add nsw i64 [[TMP19]], 1 +// CHECK1-NEXT: store i64 [[INC]], ptr [[DOTTILE_0_IV___BEGIN2]], align 8 +// CHECK1-NEXT: br label [[FOR_COND7]], !llvm.loop [[LOOP25:![0-9]+]] +// CHECK1: for.end: +// CHECK1-NEXT: br label [[FOR_INC16:%.*]] +// CHECK1: for.inc16: +// CHECK1-NEXT: [[TMP20:%.*]] = load i64, ptr [[DOTFLOOR_0_IV___BEGIN2]], align 8 +// CHECK1-NEXT: [[ADD17:%.*]] = add nsw i64 [[TMP20]], 5 +// CHECK1-NEXT: store i64 [[ADD17]], ptr [[DOTFLOOR_0_IV___BEGIN2]], align 8 +// CHECK1-NEXT: br label [[FOR_COND]], !llvm.loop [[LOOP26:![0-9]+]] +// CHECK1: for.end18: +// CHECK1-NEXT: ret void +// +// +// CHECK1-LABEL: define dso_local void @foo10( +// CHECK1-SAME: ptr noundef byval([[STRUCT_DATA_T:%.*]]) align 8 [[DATA:%.*]]) #[[ATTR0]] { +// CHECK1-NEXT: entry: +// CHECK1-NEXT: [[C:%.*]] = alloca double, align 8 +// CHECK1-NEXT: [[__RANGE2:%.*]] = alloca ptr, align 8 +// CHECK1-NEXT: [[__END2:%.*]] = alloca ptr, align 8 +// CHECK1-NEXT: [[__BEGIN2:%.*]] = alloca ptr, align 8 +// CHECK1-NEXT: [[DOTCAPTURE_EXPR_:%.*]] = alloca ptr, align 8 +// CHECK1-NEXT: [[DOTCAPTURE_EXPR_3:%.*]] = alloca ptr, align 8 +// CHECK1-NEXT: [[DOTCAPTURE_EXPR_4:%.*]] = alloca i64, align 8 +// CHECK1-NEXT: [[DOTFLOOR_0_IV___BEGIN2:%.*]] = alloca i64, align 8 +// CHECK1-NEXT: [[DOTTILE_0_IV___BEGIN2:%.*]] = alloca i64, align 8 +// CHECK1-NEXT: [[V:%.*]] = alloca double, align 8 +// CHECK1-NEXT: store double 4.200000e+01, ptr [[C]], align 8 +// CHECK1-NEXT: [[ARRAY:%.*]] = getelementptr inbounds [[STRUCT_DATA_T]], ptr [[DATA]], i32 0, i32 0 +// CHECK1-NEXT: store ptr [[ARRAY]], ptr [[__RANGE2]], align 8 +// CHECK1-NEXT: [[TMP0:%.*]] = load ptr, ptr [[__RANGE2]], align 8 +// CHECK1-NEXT: [[ARRAYDECAY:%.*]] = getelementptr inbounds [12 x double], ptr [[TMP0]], i64 0, i64 0 +// CHECK1-NEXT: [[ADD_PTR:%.*]] = getelementptr inbounds double, ptr [[ARRAYDECAY]], i64 12 +// CHECK1-NEXT: store ptr [[ADD_PTR]], ptr [[__END2]], align 8 +// CHECK1-NEXT: [[TMP1:%.*]] = load ptr, ptr [[__RANGE2]], align 8 +// CHECK1-NEXT: [[ARRAYDECAY1:%.*]] = getelementptr inbounds [12 x double], ptr [[TMP1]], i64 0, i64 0 +// CHECK1-NEXT: store ptr [[ARRAYDECAY1]], ptr [[__BEGIN2]], align 8 +// CHECK1-NEXT: [[TMP2:%.*]] = load ptr, ptr [[__RANGE2]], align 8 +// CHECK1-NEXT: [[ARRAYDECAY2:%.*]] = getelementptr inbounds [12 x double], ptr [[TMP2]], i64 0, i64 0 +// CHECK1-NEXT: store ptr [[ARRAYDECAY2]], ptr [[DOTCAPTURE_EXPR_]], align 8 +// CHECK1-NEXT: [[TMP3:%.*]] = load ptr, ptr [[__END2]], align 8 +// CHECK1-NEXT: store ptr [[TMP3]], ptr [[DOTCAPTURE_EXPR_3]], align 8 +// CHECK1-NEXT: [[TMP4:%.*]] = load ptr, ptr [[DOTCAPTURE_EXPR_3]], align 8 +// CHECK1-NEXT: [[TMP5:%.*]] = load ptr, ptr [[DOTCAPTURE_EXPR_]], align 8 +// CHECK1-NEXT: [[SUB_PTR_LHS_CAST:%.*]] = ptrtoint ptr [[TMP4]] to i64 +// CHECK1-NEXT: [[SUB_PTR_RHS_CAST:%.*]] = ptrtoint ptr [[TMP5]] to i64 +// CHECK1-NEXT: [[SUB_PTR_SUB:%.*]] = sub i64 [[SUB_PTR_LHS_CAST]], [[SUB_PTR_RHS_CAST]] +// CHECK1-NEXT: [[SUB_PTR_DIV:%.*]] = sdiv exact i64 [[SUB_PTR_SUB]], 8 +// CHECK1-NEXT: [[SUB:%.*]] = sub nsw i64 [[SUB_PTR_DIV]], 1 +// CHECK1-NEXT: [[ADD:%.*]] = add nsw i64 [[SUB]], 1 +// CHECK1-NEXT: [[DIV:%.*]] = sdiv i64 [[ADD]], 1 +// CHECK1-NEXT: [[SUB5:%.*]] = sub nsw i64 [[DIV]], 1 +// CHECK1-NEXT: store i64 [[SUB5]], ptr [[DOTCAPTURE_EXPR_4]], align 8 +// CHECK1-NEXT: store i64 0, ptr [[DOTFLOOR_0_IV___BEGIN2]], align 8 +// CHECK1-NEXT: br label [[FOR_COND:%.*]] +// CHECK1: for.cond: +// CHECK1-NEXT: [[TMP6:%.*]] = load i64, ptr [[DOTFLOOR_0_IV___BEGIN2]], align 8 +// CHECK1-NEXT: [[TMP7:%.*]] = load i64, ptr [[DOTCAPTURE_EXPR_4]], align 8 +// CHECK1-NEXT: [[ADD6:%.*]] = add nsw i64 [[TMP7]], 1 +// CHECK1-NEXT: [[CMP:%.*]] = icmp slt i64 [[TMP6]], [[ADD6]] +// CHECK1-NEXT: br i1 [[CMP]], label [[FOR_BODY:%.*]], label [[FOR_END18:%.*]] +// CHECK1: for.body: +// CHECK1-NEXT: [[TMP8:%.*]] = load i64, ptr [[DOTFLOOR_0_IV___BEGIN2]], align 8 +// CHECK1-NEXT: store i64 [[TMP8]], ptr [[DOTTILE_0_IV___BEGIN2]], align 8 +// CHECK1-NEXT: br label [[FOR_COND7:%.*]] +// CHECK1: for.cond7: +// CHECK1-NEXT: [[TMP9:%.*]] = load i64, ptr [[DOTTILE_0_IV___BEGIN2]], align 8 +// CHECK1-NEXT: [[TMP10:%.*]] = load i64, ptr [[DOTCAPTURE_EXPR_4]], align 8 +// CHECK1-NEXT: [[ADD8:%.*]] = add nsw i64 [[TMP10]], 1 +// CHECK1-NEXT: [[TMP11:%.*]] = load i64, ptr [[DOTFLOOR_0_IV___BEGIN2]], align 8 +// CHECK1-NEXT: [[ADD9:%.*]] = add nsw i64 [[TMP11]], 5 +// CHECK1-NEXT: [[CMP10:%.*]] = icmp slt i64 [[ADD8]], [[ADD9]] +// CHECK1-NEXT: br i1 [[CMP10]], label [[COND_TRUE:%.*]], label [[COND_FALSE:%.*]] +// CHECK1: cond.true: +// CHECK1-NEXT: [[TMP12:%.*]] = load i64, ptr [[DOTCAPTURE_EXPR_4]], align 8 +// CHECK1-NEXT: [[ADD11:%.*]] = add nsw i64 [[TMP12]], 1 +// CHECK1-NEXT: br label [[COND_END:%.*]] +// CHECK1: cond.false: +// CHECK1-NEXT: [[TMP13:%.*]] = load i64, ptr [[DOTFLOOR_0_IV___BEGIN2]], align 8 +// CHECK1-NEXT: [[ADD12:%.*]] = add nsw i64 [[TMP13]], 5 +// CHECK1-NEXT: br label [[COND_END]] +// CHECK1: cond.end: +// CHECK1-NEXT: [[COND:%.*]] = phi i64 [ [[ADD11]], [[COND_TRUE]] ], [ [[ADD12]], [[COND_FALSE]] ] +// CHECK1-NEXT: [[CMP13:%.*]] = icmp slt i64 [[TMP9]], [[COND]] +// CHECK1-NEXT: br i1 [[CMP13]], label [[FOR_BODY14:%.*]], label [[FOR_END:%.*]] +// CHECK1: for.body14: +// CHECK1-NEXT: [[TMP14:%.*]] = load ptr, ptr [[DOTCAPTURE_EXPR_]], align 8 +// CHECK1-NEXT: [[TMP15:%.*]] = load i64, ptr [[DOTTILE_0_IV___BEGIN2]], align 8 +// CHECK1-NEXT: [[MUL:%.*]] = mul nsw i64 [[TMP15]], 1 +// CHECK1-NEXT: [[ADD_PTR15:%.*]] = getelementptr inbounds double, ptr [[TMP14]], i64 [[MUL]] +// CHECK1-NEXT: store ptr [[ADD_PTR15]], ptr [[__BEGIN2]], align 8 +// CHECK1-NEXT: [[TMP16:%.*]] = load ptr, ptr [[__BEGIN2]], align 8 +// CHECK1-NEXT: [[TMP17:%.*]] = load double, ptr [[TMP16]], align 8 +// CHECK1-NEXT: store double [[TMP17]], ptr [[V]], align 8 +// CHECK1-NEXT: [[TMP18:%.*]] = load double, ptr [[C]], align 8 +// CHECK1-NEXT: [[TMP19:%.*]] = load double, ptr [[V]], align 8 +// CHECK1-NEXT: call void (...) @body(double noundef [[TMP18]], double noundef [[TMP19]]) +// CHECK1-NEXT: br label [[FOR_INC:%.*]] +// CHECK1: for.inc: +// CHECK1-NEXT: [[TMP20:%.*]] = load i64, ptr [[DOTTILE_0_IV___BEGIN2]], align 8 +// CHECK1-NEXT: [[INC:%.*]] = add nsw i64 [[TMP20]], 1 +// CHECK1-NEXT: store i64 [[INC]], ptr [[DOTTILE_0_IV___BEGIN2]], align 8 +// CHECK1-NEXT: br label [[FOR_COND7]], !llvm.loop [[LOOP27:![0-9]+]] +// CHECK1: for.end: +// CHECK1-NEXT: br label [[FOR_INC16:%.*]] +// CHECK1: for.inc16: +// CHECK1-NEXT: [[TMP21:%.*]] = load i64, ptr [[DOTFLOOR_0_IV___BEGIN2]], align 8 +// CHECK1-NEXT: [[ADD17:%.*]] = add nsw i64 [[TMP21]], 5 +// CHECK1-NEXT: store i64 [[ADD17]], ptr [[DOTFLOOR_0_IV___BEGIN2]], align 8 +// CHECK1-NEXT: br label [[FOR_COND]], !llvm.loop [[LOOP28:![0-9]+]] +// CHECK1: for.end18: +// CHECK1-NEXT: ret void +// +// +// CHECK1-LABEL: define internal void @_GLOBAL__sub_I_tile_codegen.cpp( +// CHECK1-SAME: ) #[[ATTR1]] section ".text.startup" { // CHECK1-NEXT: entry: // CHECK1-NEXT: call void @__cxx_global_var_init() // CHECK1-NEXT: ret void // // -// CHECK2-LABEL: define {{[^@]+}}@__cxx_global_var_init -// CHECK2-SAME: () #[[ATTR0:[0-9]+]] section ".text.startup" { +// CHECK2-LABEL: define internal void @__cxx_global_var_init( +// CHECK2-SAME: ) #[[ATTR0:[0-9]+]] section ".text.startup" { // CHECK2-NEXT: entry: // CHECK2-NEXT: call void @_ZN1SC1Ev(ptr noundef nonnull align 4 dereferenceable(4) @s) // CHECK2-NEXT: ret void // // -// CHECK2-LABEL: define {{[^@]+}}@_ZN1SC1Ev -// CHECK2-SAME: (ptr noundef nonnull align 4 dereferenceable(4) [[THIS:%.*]]) unnamed_addr #[[ATTR1:[0-9]+]] comdat align 2 { +// CHECK2-LABEL: define linkonce_odr void @_ZN1SC1Ev( +// CHECK2-SAME: ptr noundef nonnull align 4 dereferenceable(4) [[THIS:%.*]]) unnamed_addr #[[ATTR1:[0-9]+]] comdat align 2 { // CHECK2-NEXT: entry: // CHECK2-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 8 // CHECK2-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 8 @@ -1192,50 +1409,52 @@ extern "C" void foo8(int a) { // CHECK2-NEXT: ret void // // -// CHECK2-LABEL: define {{[^@]+}}@_ZN1SC2Ev -// CHECK2-SAME: (ptr noundef nonnull align 4 dereferenceable(4) [[THIS:%.*]]) unnamed_addr #[[ATTR1]] comdat align 2 { +// CHECK2-LABEL: define linkonce_odr void @_ZN1SC2Ev( +// CHECK2-SAME: ptr noundef nonnull align 4 dereferenceable(4) [[THIS:%.*]]) unnamed_addr #[[ATTR1]] comdat align 2 { // CHECK2-NEXT: entry: // CHECK2-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 8 -// CHECK2-NEXT: [[I:%.*]] = alloca ptr, align 8 +// CHECK2-NEXT: [[I2:%.*]] = alloca ptr, align 8 // CHECK2-NEXT: [[DOTFLOOR_0_IV_I:%.*]] = alloca i32, align 4 // CHECK2-NEXT: [[DOTTILE_0_IV_I:%.*]] = alloca i32, align 4 // CHECK2-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 8 // CHECK2-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8 -// CHECK2-NEXT: [[I2:%.*]] = getelementptr inbounds [[STRUCT_S:%.*]], ptr [[THIS1]], i32 0, i32 0 -// CHECK2-NEXT: store ptr [[I2]], ptr [[I]], align 8 +// CHECK2-NEXT: [[I:%.*]] = getelementptr inbounds [[STRUCT_S:%.*]], ptr [[THIS1]], i32 0, i32 0 +// CHECK2-NEXT: store i32 7, ptr [[I]], align 4 +// CHECK2-NEXT: [[I3:%.*]] = getelementptr inbounds [[STRUCT_S]], ptr [[THIS1]], i32 0, i32 0 +// CHECK2-NEXT: store ptr [[I3]], ptr [[I2]], align 8 // CHECK2-NEXT: store i32 0, ptr [[DOTFLOOR_0_IV_I]], align 4 // CHECK2-NEXT: br label [[FOR_COND:%.*]] // CHECK2: for.cond: // CHECK2-NEXT: [[TMP0:%.*]] = load i32, ptr [[DOTFLOOR_0_IV_I]], align 4 // CHECK2-NEXT: [[CMP:%.*]] = icmp slt i32 [[TMP0]], 4 -// CHECK2-NEXT: br i1 [[CMP]], label [[FOR_BODY:%.*]], label [[FOR_END11:%.*]] +// CHECK2-NEXT: br i1 [[CMP]], label [[FOR_BODY:%.*]], label [[FOR_END12:%.*]] // CHECK2: for.body: // CHECK2-NEXT: [[TMP1:%.*]] = load i32, ptr [[DOTFLOOR_0_IV_I]], align 4 // CHECK2-NEXT: store i32 [[TMP1]], ptr [[DOTTILE_0_IV_I]], align 4 -// CHECK2-NEXT: br label [[FOR_COND3:%.*]] -// CHECK2: for.cond3: +// CHECK2-NEXT: br label [[FOR_COND4:%.*]] +// CHECK2: for.cond4: // CHECK2-NEXT: [[TMP2:%.*]] = load i32, ptr [[DOTTILE_0_IV_I]], align 4 // CHECK2-NEXT: [[TMP3:%.*]] = load i32, ptr [[DOTFLOOR_0_IV_I]], align 4 // CHECK2-NEXT: [[ADD:%.*]] = add nsw i32 [[TMP3]], 5 -// CHECK2-NEXT: [[CMP4:%.*]] = icmp slt i32 4, [[ADD]] -// CHECK2-NEXT: br i1 [[CMP4]], label [[COND_TRUE:%.*]], label [[COND_FALSE:%.*]] +// CHECK2-NEXT: [[CMP5:%.*]] = icmp slt i32 4, [[ADD]] +// CHECK2-NEXT: br i1 [[CMP5]], label [[COND_TRUE:%.*]], label [[COND_FALSE:%.*]] // CHECK2: cond.true: // CHECK2-NEXT: br label [[COND_END:%.*]] // CHECK2: cond.false: // CHECK2-NEXT: [[TMP4:%.*]] = load i32, ptr [[DOTFLOOR_0_IV_I]], align 4 -// CHECK2-NEXT: [[ADD5:%.*]] = add nsw i32 [[TMP4]], 5 +// CHECK2-NEXT: [[ADD6:%.*]] = add nsw i32 [[TMP4]], 5 // CHECK2-NEXT: br label [[COND_END]] // CHECK2: cond.end: -// CHECK2-NEXT: [[COND:%.*]] = phi i32 [ 4, [[COND_TRUE]] ], [ [[ADD5]], [[COND_FALSE]] ] -// CHECK2-NEXT: [[CMP6:%.*]] = icmp slt i32 [[TMP2]], [[COND]] -// CHECK2-NEXT: br i1 [[CMP6]], label [[FOR_BODY7:%.*]], label [[FOR_END:%.*]] -// CHECK2: for.body7: +// CHECK2-NEXT: [[COND:%.*]] = phi i32 [ 4, [[COND_TRUE]] ], [ [[ADD6]], [[COND_FALSE]] ] +// CHECK2-NEXT: [[CMP7:%.*]] = icmp slt i32 [[TMP2]], [[COND]] +// CHECK2-NEXT: br i1 [[CMP7]], label [[FOR_BODY8:%.*]], label [[FOR_END:%.*]] +// CHECK2: for.body8: // CHECK2-NEXT: [[TMP5:%.*]] = load i32, ptr [[DOTTILE_0_IV_I]], align 4 // CHECK2-NEXT: [[MUL:%.*]] = mul nsw i32 [[TMP5]], 3 -// CHECK2-NEXT: [[ADD8:%.*]] = add nsw i32 7, [[MUL]] -// CHECK2-NEXT: [[TMP6:%.*]] = load ptr, ptr [[I]], align 8 -// CHECK2-NEXT: store i32 [[ADD8]], ptr [[TMP6]], align 4 -// CHECK2-NEXT: [[TMP7:%.*]] = load ptr, ptr [[I]], align 8 +// CHECK2-NEXT: [[ADD9:%.*]] = add nsw i32 7, [[MUL]] +// CHECK2-NEXT: [[TMP6:%.*]] = load ptr, ptr [[I2]], align 8 +// CHECK2-NEXT: store i32 [[ADD9]], ptr [[TMP6]], align 4 +// CHECK2-NEXT: [[TMP7:%.*]] = load ptr, ptr [[I2]], align 8 // CHECK2-NEXT: [[TMP8:%.*]] = load i32, ptr [[TMP7]], align 4 // CHECK2-NEXT: call void (...) @body(i32 noundef [[TMP8]]) // CHECK2-NEXT: br label [[FOR_INC:%.*]] @@ -1243,26 +1462,26 @@ extern "C" void foo8(int a) { // CHECK2-NEXT: [[TMP9:%.*]] = load i32, ptr [[DOTTILE_0_IV_I]], align 4 // CHECK2-NEXT: [[INC:%.*]] = add nsw i32 [[TMP9]], 1 // CHECK2-NEXT: store i32 [[INC]], ptr [[DOTTILE_0_IV_I]], align 4 -// CHECK2-NEXT: br label [[FOR_COND3]], !llvm.loop [[LOOP3:![0-9]+]] +// CHECK2-NEXT: br label [[FOR_COND4]], !llvm.loop [[LOOP3:![0-9]+]] // CHECK2: for.end: -// CHECK2-NEXT: br label [[FOR_INC9:%.*]] -// CHECK2: for.inc9: +// CHECK2-NEXT: br label [[FOR_INC10:%.*]] +// CHECK2: for.inc10: // CHECK2-NEXT: [[TMP10:%.*]] = load i32, ptr [[DOTFLOOR_0_IV_I]], align 4 -// CHECK2-NEXT: [[ADD10:%.*]] = add nsw i32 [[TMP10]], 5 -// CHECK2-NEXT: store i32 [[ADD10]], ptr [[DOTFLOOR_0_IV_I]], align 4 +// CHECK2-NEXT: [[ADD11:%.*]] = add nsw i32 [[TMP10]], 5 +// CHECK2-NEXT: store i32 [[ADD11]], ptr [[DOTFLOOR_0_IV_I]], align 4 // CHECK2-NEXT: br label [[FOR_COND]], !llvm.loop [[LOOP5:![0-9]+]] -// CHECK2: for.end11: +// CHECK2: for.end12: // CHECK2-NEXT: ret void // // -// CHECK2-LABEL: define {{[^@]+}}@body -// CHECK2-SAME: (...) #[[ATTR1]] { +// CHECK2-LABEL: define dso_local void @body( +// CHECK2-SAME: ...) #[[ATTR1]] { // CHECK2-NEXT: entry: // CHECK2-NEXT: ret void // // -// CHECK2-LABEL: define {{[^@]+}}@foo1 -// CHECK2-SAME: (i32 noundef [[START:%.*]], i32 noundef [[END:%.*]], i32 noundef [[STEP:%.*]]) #[[ATTR1]] { +// CHECK2-LABEL: define dso_local void @foo1( +// CHECK2-SAME: i32 noundef [[START:%.*]], i32 noundef [[END:%.*]], i32 noundef [[STEP:%.*]]) #[[ATTR1]] { // CHECK2-NEXT: entry: // CHECK2-NEXT: [[START_ADDR:%.*]] = alloca i32, align 4 // CHECK2-NEXT: [[END_ADDR:%.*]] = alloca i32, align 4 @@ -1278,81 +1497,183 @@ extern "C" void foo8(int a) { // CHECK2-NEXT: store i32 [[END]], ptr [[END_ADDR]], align 4 // CHECK2-NEXT: store i32 [[STEP]], ptr [[STEP_ADDR]], align 4 // CHECK2-NEXT: [[TMP0:%.*]] = load i32, ptr [[START_ADDR]], align 4 -// CHECK2-NEXT: store i32 [[TMP0]], ptr [[DOTCAPTURE_EXPR_]], align 4 -// CHECK2-NEXT: [[TMP1:%.*]] = load i32, ptr [[END_ADDR]], align 4 -// CHECK2-NEXT: store i32 [[TMP1]], ptr [[DOTCAPTURE_EXPR_1]], align 4 -// CHECK2-NEXT: [[TMP2:%.*]] = load i32, ptr [[STEP_ADDR]], align 4 -// CHECK2-NEXT: store i32 [[TMP2]], ptr [[DOTNEW_STEP]], align 4 -// CHECK2-NEXT: [[TMP3:%.*]] = load i32, ptr [[DOTCAPTURE_EXPR_1]], align 4 -// CHECK2-NEXT: [[TMP4:%.*]] = load i32, ptr [[DOTCAPTURE_EXPR_]], align 4 -// CHECK2-NEXT: [[SUB:%.*]] = sub i32 [[TMP3]], [[TMP4]] +// CHECK2-NEXT: store i32 [[TMP0]], ptr [[I]], align 4 +// CHECK2-NEXT: [[TMP1:%.*]] = load i32, ptr [[START_ADDR]], align 4 +// CHECK2-NEXT: store i32 [[TMP1]], ptr [[DOTCAPTURE_EXPR_]], align 4 +// CHECK2-NEXT: [[TMP2:%.*]] = load i32, ptr [[END_ADDR]], align 4 +// CHECK2-NEXT: store i32 [[TMP2]], ptr [[DOTCAPTURE_EXPR_1]], align 4 +// CHECK2-NEXT: [[TMP3:%.*]] = load i32, ptr [[STEP_ADDR]], align 4 +// CHECK2-NEXT: store i32 [[TMP3]], ptr [[DOTNEW_STEP]], align 4 +// CHECK2-NEXT: [[TMP4:%.*]] = load i32, ptr [[DOTCAPTURE_EXPR_1]], align 4 +// CHECK2-NEXT: [[TMP5:%.*]] = load i32, ptr [[DOTCAPTURE_EXPR_]], align 4 +// CHECK2-NEXT: [[SUB:%.*]] = sub i32 [[TMP4]], [[TMP5]] // CHECK2-NEXT: [[SUB3:%.*]] = sub i32 [[SUB]], 1 -// CHECK2-NEXT: [[TMP5:%.*]] = load i32, ptr [[DOTNEW_STEP]], align 4 -// CHECK2-NEXT: [[ADD:%.*]] = add i32 [[SUB3]], [[TMP5]] // CHECK2-NEXT: [[TMP6:%.*]] = load i32, ptr [[DOTNEW_STEP]], align 4 -// CHECK2-NEXT: [[DIV:%.*]] = udiv i32 [[ADD]], [[TMP6]] +// CHECK2-NEXT: [[ADD:%.*]] = add i32 [[SUB3]], [[TMP6]] +// CHECK2-NEXT: [[TMP7:%.*]] = load i32, ptr [[DOTNEW_STEP]], align 4 +// CHECK2-NEXT: [[DIV:%.*]] = udiv i32 [[ADD]], [[TMP7]] // CHECK2-NEXT: [[SUB4:%.*]] = sub i32 [[DIV]], 1 // CHECK2-NEXT: store i32 [[SUB4]], ptr [[DOTCAPTURE_EXPR_2]], align 4 // CHECK2-NEXT: store i32 0, ptr [[DOTFLOOR_0_IV_I]], align 4 // CHECK2-NEXT: br label [[FOR_COND:%.*]] // CHECK2: for.cond: -// CHECK2-NEXT: [[TMP7:%.*]] = load i32, ptr [[DOTFLOOR_0_IV_I]], align 4 -// CHECK2-NEXT: [[TMP8:%.*]] = load i32, ptr [[DOTCAPTURE_EXPR_2]], align 4 -// CHECK2-NEXT: [[ADD5:%.*]] = add i32 [[TMP8]], 1 -// CHECK2-NEXT: [[CMP:%.*]] = icmp ult i32 [[TMP7]], [[ADD5]] +// CHECK2-NEXT: [[TMP8:%.*]] = load i32, ptr [[DOTFLOOR_0_IV_I]], align 4 +// CHECK2-NEXT: [[TMP9:%.*]] = load i32, ptr [[DOTCAPTURE_EXPR_2]], align 4 +// CHECK2-NEXT: [[ADD5:%.*]] = add i32 [[TMP9]], 1 +// CHECK2-NEXT: [[CMP:%.*]] = icmp ult i32 [[TMP8]], [[ADD5]] // CHECK2-NEXT: br i1 [[CMP]], label [[FOR_BODY:%.*]], label [[FOR_END17:%.*]] // CHECK2: for.body: -// CHECK2-NEXT: [[TMP9:%.*]] = load i32, ptr [[DOTFLOOR_0_IV_I]], align 4 -// CHECK2-NEXT: store i32 [[TMP9]], ptr [[DOTTILE_0_IV_I]], align 4 +// CHECK2-NEXT: [[TMP10:%.*]] = load i32, ptr [[DOTFLOOR_0_IV_I]], align 4 +// CHECK2-NEXT: store i32 [[TMP10]], ptr [[DOTTILE_0_IV_I]], align 4 // CHECK2-NEXT: br label [[FOR_COND6:%.*]] // CHECK2: for.cond6: -// CHECK2-NEXT: [[TMP10:%.*]] = load i32, ptr [[DOTTILE_0_IV_I]], align 4 -// CHECK2-NEXT: [[TMP11:%.*]] = load i32, ptr [[DOTCAPTURE_EXPR_2]], align 4 -// CHECK2-NEXT: [[ADD7:%.*]] = add i32 [[TMP11]], 1 -// CHECK2-NEXT: [[TMP12:%.*]] = load i32, ptr [[DOTFLOOR_0_IV_I]], align 4 -// CHECK2-NEXT: [[ADD8:%.*]] = add nsw i32 [[TMP12]], 5 +// CHECK2-NEXT: [[TMP11:%.*]] = load i32, ptr [[DOTTILE_0_IV_I]], align 4 +// CHECK2-NEXT: [[TMP12:%.*]] = load i32, ptr [[DOTCAPTURE_EXPR_2]], align 4 +// CHECK2-NEXT: [[ADD7:%.*]] = add i32 [[TMP12]], 1 +// CHECK2-NEXT: [[TMP13:%.*]] = load i32, ptr [[DOTFLOOR_0_IV_I]], align 4 +// CHECK2-NEXT: [[ADD8:%.*]] = add i32 [[TMP13]], 5 // CHECK2-NEXT: [[CMP9:%.*]] = icmp ult i32 [[ADD7]], [[ADD8]] // CHECK2-NEXT: br i1 [[CMP9]], label [[COND_TRUE:%.*]], label [[COND_FALSE:%.*]] // CHECK2: cond.true: -// CHECK2-NEXT: [[TMP13:%.*]] = load i32, ptr [[DOTCAPTURE_EXPR_2]], align 4 -// CHECK2-NEXT: [[ADD10:%.*]] = add i32 [[TMP13]], 1 +// CHECK2-NEXT: [[TMP14:%.*]] = load i32, ptr [[DOTCAPTURE_EXPR_2]], align 4 +// CHECK2-NEXT: [[ADD10:%.*]] = add i32 [[TMP14]], 1 // CHECK2-NEXT: br label [[COND_END:%.*]] // CHECK2: cond.false: -// CHECK2-NEXT: [[TMP14:%.*]] = load i32, ptr [[DOTFLOOR_0_IV_I]], align 4 -// CHECK2-NEXT: [[ADD11:%.*]] = add nsw i32 [[TMP14]], 5 +// CHECK2-NEXT: [[TMP15:%.*]] = load i32, ptr [[DOTFLOOR_0_IV_I]], align 4 +// CHECK2-NEXT: [[ADD11:%.*]] = add i32 [[TMP15]], 5 // CHECK2-NEXT: br label [[COND_END]] // CHECK2: cond.end: // CHECK2-NEXT: [[COND:%.*]] = phi i32 [ [[ADD10]], [[COND_TRUE]] ], [ [[ADD11]], [[COND_FALSE]] ] -// CHECK2-NEXT: [[CMP12:%.*]] = icmp ult i32 [[TMP10]], [[COND]] +// CHECK2-NEXT: [[CMP12:%.*]] = icmp ult i32 [[TMP11]], [[COND]] // CHECK2-NEXT: br i1 [[CMP12]], label [[FOR_BODY13:%.*]], label [[FOR_END:%.*]] // CHECK2: for.body13: -// CHECK2-NEXT: [[TMP15:%.*]] = load i32, ptr [[DOTCAPTURE_EXPR_]], align 4 -// CHECK2-NEXT: [[TMP16:%.*]] = load i32, ptr [[DOTTILE_0_IV_I]], align 4 -// CHECK2-NEXT: [[TMP17:%.*]] = load i32, ptr [[DOTNEW_STEP]], align 4 -// CHECK2-NEXT: [[MUL:%.*]] = mul i32 [[TMP16]], [[TMP17]] -// CHECK2-NEXT: [[ADD14:%.*]] = add i32 [[TMP15]], [[MUL]] +// CHECK2-NEXT: [[TMP16:%.*]] = load i32, ptr [[DOTCAPTURE_EXPR_]], align 4 +// CHECK2-NEXT: [[TMP17:%.*]] = load i32, ptr [[DOTTILE_0_IV_I]], align 4 +// CHECK2-NEXT: [[TMP18:%.*]] = load i32, ptr [[DOTNEW_STEP]], align 4 +// CHECK2-NEXT: [[MUL:%.*]] = mul i32 [[TMP17]], [[TMP18]] +// CHECK2-NEXT: [[ADD14:%.*]] = add i32 [[TMP16]], [[MUL]] // CHECK2-NEXT: store i32 [[ADD14]], ptr [[I]], align 4 -// CHECK2-NEXT: [[TMP18:%.*]] = load i32, ptr [[I]], align 4 -// CHECK2-NEXT: call void (...) @body(i32 noundef [[TMP18]]) +// CHECK2-NEXT: [[TMP19:%.*]] = load i32, ptr [[I]], align 4 +// CHECK2-NEXT: call void (...) @body(i32 noundef [[TMP19]]) // CHECK2-NEXT: br label [[FOR_INC:%.*]] // CHECK2: for.inc: -// CHECK2-NEXT: [[TMP19:%.*]] = load i32, ptr [[DOTTILE_0_IV_I]], align 4 -// CHECK2-NEXT: [[INC:%.*]] = add nsw i32 [[TMP19]], 1 +// CHECK2-NEXT: [[TMP20:%.*]] = load i32, ptr [[DOTTILE_0_IV_I]], align 4 +// CHECK2-NEXT: [[INC:%.*]] = add i32 [[TMP20]], 1 // CHECK2-NEXT: store i32 [[INC]], ptr [[DOTTILE_0_IV_I]], align 4 // CHECK2-NEXT: br label [[FOR_COND6]], !llvm.loop [[LOOP6:![0-9]+]] // CHECK2: for.end: // CHECK2-NEXT: br label [[FOR_INC15:%.*]] // CHECK2: for.inc15: -// CHECK2-NEXT: [[TMP20:%.*]] = load i32, ptr [[DOTFLOOR_0_IV_I]], align 4 -// CHECK2-NEXT: [[ADD16:%.*]] = add nsw i32 [[TMP20]], 5 +// CHECK2-NEXT: [[TMP21:%.*]] = load i32, ptr [[DOTFLOOR_0_IV_I]], align 4 +// CHECK2-NEXT: [[ADD16:%.*]] = add i32 [[TMP21]], 5 // CHECK2-NEXT: store i32 [[ADD16]], ptr [[DOTFLOOR_0_IV_I]], align 4 // CHECK2-NEXT: br label [[FOR_COND]], !llvm.loop [[LOOP7:![0-9]+]] // CHECK2: for.end17: // CHECK2-NEXT: ret void // // -// CHECK2-LABEL: define {{[^@]+}}@foo2 -// CHECK2-SAME: (i32 noundef [[START:%.*]], i32 noundef [[END:%.*]], i32 noundef [[STEP:%.*]]) #[[ATTR1]] { +// CHECK2-LABEL: define dso_local void @foo10( +// CHECK2-SAME: ptr noundef byval([[STRUCT_DATA_T:%.*]]) align 8 [[DATA:%.*]]) #[[ATTR1]] { +// CHECK2-NEXT: entry: +// CHECK2-NEXT: [[C:%.*]] = alloca double, align 8 +// CHECK2-NEXT: [[__RANGE2:%.*]] = alloca ptr, align 8 +// CHECK2-NEXT: [[__END2:%.*]] = alloca ptr, align 8 +// CHECK2-NEXT: [[__BEGIN2:%.*]] = alloca ptr, align 8 +// CHECK2-NEXT: [[DOTCAPTURE_EXPR_:%.*]] = alloca ptr, align 8 +// CHECK2-NEXT: [[DOTCAPTURE_EXPR_3:%.*]] = alloca ptr, align 8 +// CHECK2-NEXT: [[DOTCAPTURE_EXPR_4:%.*]] = alloca i64, align 8 +// CHECK2-NEXT: [[DOTFLOOR_0_IV___BEGIN2:%.*]] = alloca i64, align 8 +// CHECK2-NEXT: [[DOTTILE_0_IV___BEGIN2:%.*]] = alloca i64, align 8 +// CHECK2-NEXT: [[V:%.*]] = alloca double, align 8 +// CHECK2-NEXT: store double 4.200000e+01, ptr [[C]], align 8 +// CHECK2-NEXT: [[ARRAY:%.*]] = getelementptr inbounds [[STRUCT_DATA_T]], ptr [[DATA]], i32 0, i32 0 +// CHECK2-NEXT: store ptr [[ARRAY]], ptr [[__RANGE2]], align 8 +// CHECK2-NEXT: [[TMP0:%.*]] = load ptr, ptr [[__RANGE2]], align 8 +// CHECK2-NEXT: [[ARRAYDECAY:%.*]] = getelementptr inbounds [12 x double], ptr [[TMP0]], i64 0, i64 0 +// CHECK2-NEXT: [[ADD_PTR:%.*]] = getelementptr inbounds double, ptr [[ARRAYDECAY]], i64 12 +// CHECK2-NEXT: store ptr [[ADD_PTR]], ptr [[__END2]], align 8 +// CHECK2-NEXT: [[TMP1:%.*]] = load ptr, ptr [[__RANGE2]], align 8 +// CHECK2-NEXT: [[ARRAYDECAY1:%.*]] = getelementptr inbounds [12 x double], ptr [[TMP1]], i64 0, i64 0 +// CHECK2-NEXT: store ptr [[ARRAYDECAY1]], ptr [[__BEGIN2]], align 8 +// CHECK2-NEXT: [[TMP2:%.*]] = load ptr, ptr [[__RANGE2]], align 8 +// CHECK2-NEXT: [[ARRAYDECAY2:%.*]] = getelementptr inbounds [12 x double], ptr [[TMP2]], i64 0, i64 0 +// CHECK2-NEXT: store ptr [[ARRAYDECAY2]], ptr [[DOTCAPTURE_EXPR_]], align 8 +// CHECK2-NEXT: [[TMP3:%.*]] = load ptr, ptr [[__END2]], align 8 +// CHECK2-NEXT: store ptr [[TMP3]], ptr [[DOTCAPTURE_EXPR_3]], align 8 +// CHECK2-NEXT: [[TMP4:%.*]] = load ptr, ptr [[DOTCAPTURE_EXPR_3]], align 8 +// CHECK2-NEXT: [[TMP5:%.*]] = load ptr, ptr [[DOTCAPTURE_EXPR_]], align 8 +// CHECK2-NEXT: [[SUB_PTR_LHS_CAST:%.*]] = ptrtoint ptr [[TMP4]] to i64 +// CHECK2-NEXT: [[SUB_PTR_RHS_CAST:%.*]] = ptrtoint ptr [[TMP5]] to i64 +// CHECK2-NEXT: [[SUB_PTR_SUB:%.*]] = sub i64 [[SUB_PTR_LHS_CAST]], [[SUB_PTR_RHS_CAST]] +// CHECK2-NEXT: [[SUB_PTR_DIV:%.*]] = sdiv exact i64 [[SUB_PTR_SUB]], 8 +// CHECK2-NEXT: [[SUB:%.*]] = sub nsw i64 [[SUB_PTR_DIV]], 1 +// CHECK2-NEXT: [[ADD:%.*]] = add nsw i64 [[SUB]], 1 +// CHECK2-NEXT: [[DIV:%.*]] = sdiv i64 [[ADD]], 1 +// CHECK2-NEXT: [[SUB5:%.*]] = sub nsw i64 [[DIV]], 1 +// CHECK2-NEXT: store i64 [[SUB5]], ptr [[DOTCAPTURE_EXPR_4]], align 8 +// CHECK2-NEXT: store i64 0, ptr [[DOTFLOOR_0_IV___BEGIN2]], align 8 +// CHECK2-NEXT: br label [[FOR_COND:%.*]] +// CHECK2: for.cond: +// CHECK2-NEXT: [[TMP6:%.*]] = load i64, ptr [[DOTFLOOR_0_IV___BEGIN2]], align 8 +// CHECK2-NEXT: [[TMP7:%.*]] = load i64, ptr [[DOTCAPTURE_EXPR_4]], align 8 +// CHECK2-NEXT: [[ADD6:%.*]] = add nsw i64 [[TMP7]], 1 +// CHECK2-NEXT: [[CMP:%.*]] = icmp slt i64 [[TMP6]], [[ADD6]] +// CHECK2-NEXT: br i1 [[CMP]], label [[FOR_BODY:%.*]], label [[FOR_END18:%.*]] +// CHECK2: for.body: +// CHECK2-NEXT: [[TMP8:%.*]] = load i64, ptr [[DOTFLOOR_0_IV___BEGIN2]], align 8 +// CHECK2-NEXT: store i64 [[TMP8]], ptr [[DOTTILE_0_IV___BEGIN2]], align 8 +// CHECK2-NEXT: br label [[FOR_COND7:%.*]] +// CHECK2: for.cond7: +// CHECK2-NEXT: [[TMP9:%.*]] = load i64, ptr [[DOTTILE_0_IV___BEGIN2]], align 8 +// CHECK2-NEXT: [[TMP10:%.*]] = load i64, ptr [[DOTCAPTURE_EXPR_4]], align 8 +// CHECK2-NEXT: [[ADD8:%.*]] = add nsw i64 [[TMP10]], 1 +// CHECK2-NEXT: [[TMP11:%.*]] = load i64, ptr [[DOTFLOOR_0_IV___BEGIN2]], align 8 +// CHECK2-NEXT: [[ADD9:%.*]] = add nsw i64 [[TMP11]], 5 +// CHECK2-NEXT: [[CMP10:%.*]] = icmp slt i64 [[ADD8]], [[ADD9]] +// CHECK2-NEXT: br i1 [[CMP10]], label [[COND_TRUE:%.*]], label [[COND_FALSE:%.*]] +// CHECK2: cond.true: +// CHECK2-NEXT: [[TMP12:%.*]] = load i64, ptr [[DOTCAPTURE_EXPR_4]], align 8 +// CHECK2-NEXT: [[ADD11:%.*]] = add nsw i64 [[TMP12]], 1 +// CHECK2-NEXT: br label [[COND_END:%.*]] +// CHECK2: cond.false: +// CHECK2-NEXT: [[TMP13:%.*]] = load i64, ptr [[DOTFLOOR_0_IV___BEGIN2]], align 8 +// CHECK2-NEXT: [[ADD12:%.*]] = add nsw i64 [[TMP13]], 5 +// CHECK2-NEXT: br label [[COND_END]] +// CHECK2: cond.end: +// CHECK2-NEXT: [[COND:%.*]] = phi i64 [ [[ADD11]], [[COND_TRUE]] ], [ [[ADD12]], [[COND_FALSE]] ] +// CHECK2-NEXT: [[CMP13:%.*]] = icmp slt i64 [[TMP9]], [[COND]] +// CHECK2-NEXT: br i1 [[CMP13]], label [[FOR_BODY14:%.*]], label [[FOR_END:%.*]] +// CHECK2: for.body14: +// CHECK2-NEXT: [[TMP14:%.*]] = load ptr, ptr [[DOTCAPTURE_EXPR_]], align 8 +// CHECK2-NEXT: [[TMP15:%.*]] = load i64, ptr [[DOTTILE_0_IV___BEGIN2]], align 8 +// CHECK2-NEXT: [[MUL:%.*]] = mul nsw i64 [[TMP15]], 1 +// CHECK2-NEXT: [[ADD_PTR15:%.*]] = getelementptr inbounds double, ptr [[TMP14]], i64 [[MUL]] +// CHECK2-NEXT: store ptr [[ADD_PTR15]], ptr [[__BEGIN2]], align 8 +// CHECK2-NEXT: [[TMP16:%.*]] = load ptr, ptr [[__BEGIN2]], align 8 +// CHECK2-NEXT: [[TMP17:%.*]] = load double, ptr [[TMP16]], align 8 +// CHECK2-NEXT: store double [[TMP17]], ptr [[V]], align 8 +// CHECK2-NEXT: [[TMP18:%.*]] = load double, ptr [[C]], align 8 +// CHECK2-NEXT: [[TMP19:%.*]] = load double, ptr [[V]], align 8 +// CHECK2-NEXT: call void (...) @body(double noundef [[TMP18]], double noundef [[TMP19]]) +// CHECK2-NEXT: br label [[FOR_INC:%.*]] +// CHECK2: for.inc: +// CHECK2-NEXT: [[TMP20:%.*]] = load i64, ptr [[DOTTILE_0_IV___BEGIN2]], align 8 +// CHECK2-NEXT: [[INC:%.*]] = add nsw i64 [[TMP20]], 1 +// CHECK2-NEXT: store i64 [[INC]], ptr [[DOTTILE_0_IV___BEGIN2]], align 8 +// CHECK2-NEXT: br label [[FOR_COND7]], !llvm.loop [[LOOP8:![0-9]+]] +// CHECK2: for.end: +// CHECK2-NEXT: br label [[FOR_INC16:%.*]] +// CHECK2: for.inc16: +// CHECK2-NEXT: [[TMP21:%.*]] = load i64, ptr [[DOTFLOOR_0_IV___BEGIN2]], align 8 +// CHECK2-NEXT: [[ADD17:%.*]] = add nsw i64 [[TMP21]], 5 +// CHECK2-NEXT: store i64 [[ADD17]], ptr [[DOTFLOOR_0_IV___BEGIN2]], align 8 +// CHECK2-NEXT: br label [[FOR_COND]], !llvm.loop [[LOOP9:![0-9]+]] +// CHECK2: for.end18: +// CHECK2-NEXT: ret void +// +// +// CHECK2-LABEL: define dso_local void @foo2( +// CHECK2-SAME: i32 noundef [[START:%.*]], i32 noundef [[END:%.*]], i32 noundef [[STEP:%.*]]) #[[ATTR1]] { // CHECK2-NEXT: entry: // CHECK2-NEXT: [[START_ADDR:%.*]] = alloca i32, align 4 // CHECK2-NEXT: [[END_ADDR:%.*]] = alloca i32, align 4 @@ -1438,34 +1759,34 @@ extern "C" void foo8(int a) { // CHECK2-NEXT: [[TMP14:%.*]] = load i32, ptr [[DOTTILE_1_IV_J]], align 4 // CHECK2-NEXT: [[INC:%.*]] = add nsw i32 [[TMP14]], 1 // CHECK2-NEXT: store i32 [[INC]], ptr [[DOTTILE_1_IV_J]], align 4 -// CHECK2-NEXT: br label [[FOR_COND10]], !llvm.loop [[LOOP8:![0-9]+]] +// CHECK2-NEXT: br label [[FOR_COND10]], !llvm.loop [[LOOP10:![0-9]+]] // CHECK2: for.end: // CHECK2-NEXT: br label [[FOR_INC22:%.*]] // CHECK2: for.inc22: // CHECK2-NEXT: [[TMP15:%.*]] = load i32, ptr [[DOTTILE_0_IV_I]], align 4 // CHECK2-NEXT: [[INC23:%.*]] = add nsw i32 [[TMP15]], 1 // CHECK2-NEXT: store i32 [[INC23]], ptr [[DOTTILE_0_IV_I]], align 4 -// CHECK2-NEXT: br label [[FOR_COND4]], !llvm.loop [[LOOP9:![0-9]+]] +// CHECK2-NEXT: br label [[FOR_COND4]], !llvm.loop [[LOOP11:![0-9]+]] // CHECK2: for.end24: // CHECK2-NEXT: br label [[FOR_INC25:%.*]] // CHECK2: for.inc25: // CHECK2-NEXT: [[TMP16:%.*]] = load i32, ptr [[DOTFLOOR_1_IV_J]], align 4 // CHECK2-NEXT: [[ADD26:%.*]] = add nsw i32 [[TMP16]], 5 // CHECK2-NEXT: store i32 [[ADD26]], ptr [[DOTFLOOR_1_IV_J]], align 4 -// CHECK2-NEXT: br label [[FOR_COND1]], !llvm.loop [[LOOP10:![0-9]+]] +// CHECK2-NEXT: br label [[FOR_COND1]], !llvm.loop [[LOOP12:![0-9]+]] // CHECK2: for.end27: // CHECK2-NEXT: br label [[FOR_INC28:%.*]] // CHECK2: for.inc28: // CHECK2-NEXT: [[TMP17:%.*]] = load i32, ptr [[DOTFLOOR_0_IV_I]], align 4 // CHECK2-NEXT: [[ADD29:%.*]] = add nsw i32 [[TMP17]], 5 // CHECK2-NEXT: store i32 [[ADD29]], ptr [[DOTFLOOR_0_IV_I]], align 4 -// CHECK2-NEXT: br label [[FOR_COND]], !llvm.loop [[LOOP11:![0-9]+]] +// CHECK2-NEXT: br label [[FOR_COND]], !llvm.loop [[LOOP13:![0-9]+]] // CHECK2: for.end30: // CHECK2-NEXT: ret void // // -// CHECK2-LABEL: define {{[^@]+}}@foo3 -// CHECK2-SAME: () #[[ATTR1]] { +// CHECK2-LABEL: define dso_local void @foo3( +// CHECK2-SAME: ) #[[ATTR1]] { // CHECK2-NEXT: entry: // CHECK2-NEXT: [[DOTOMP_IV:%.*]] = alloca i32, align 4 // CHECK2-NEXT: [[TMP:%.*]] = alloca i32, align 4 @@ -1574,21 +1895,21 @@ extern "C" void foo8(int a) { // CHECK2-NEXT: [[TMP20:%.*]] = load i32, ptr [[DOTTILE_1_IV_J]], align 4 // CHECK2-NEXT: [[INC:%.*]] = add nsw i32 [[TMP20]], 1 // CHECK2-NEXT: store i32 [[INC]], ptr [[DOTTILE_1_IV_J]], align 4 -// CHECK2-NEXT: br label [[FOR_COND15]], !llvm.loop [[LOOP12:![0-9]+]] +// CHECK2-NEXT: br label [[FOR_COND15]], !llvm.loop [[LOOP14:![0-9]+]] // CHECK2: for.end: // CHECK2-NEXT: br label [[FOR_INC27:%.*]] // CHECK2: for.inc27: // CHECK2-NEXT: [[TMP21:%.*]] = load i32, ptr [[DOTTILE_0_IV_I]], align 4 // CHECK2-NEXT: [[INC28:%.*]] = add nsw i32 [[TMP21]], 1 // CHECK2-NEXT: store i32 [[INC28]], ptr [[DOTTILE_0_IV_I]], align 4 -// CHECK2-NEXT: br label [[FOR_COND3]], !llvm.loop [[LOOP13:![0-9]+]] +// CHECK2-NEXT: br label [[FOR_COND3]], !llvm.loop [[LOOP15:![0-9]+]] // CHECK2: for.end29: // CHECK2-NEXT: br label [[FOR_INC30:%.*]] // CHECK2: for.inc30: // CHECK2-NEXT: [[TMP22:%.*]] = load i32, ptr [[DOTFLOOR_1_IV_J]], align 4 // CHECK2-NEXT: [[ADD31:%.*]] = add nsw i32 [[TMP22]], 5 // CHECK2-NEXT: store i32 [[ADD31]], ptr [[DOTFLOOR_1_IV_J]], align 4 -// CHECK2-NEXT: br label [[FOR_COND]], !llvm.loop [[LOOP14:![0-9]+]] +// CHECK2-NEXT: br label [[FOR_COND]], !llvm.loop [[LOOP16:![0-9]+]] // CHECK2: for.end32: // CHECK2-NEXT: br label [[OMP_BODY_CONTINUE:%.*]] // CHECK2: omp.body.continue: @@ -1606,8 +1927,8 @@ extern "C" void foo8(int a) { // CHECK2-NEXT: ret void // // -// CHECK2-LABEL: define {{[^@]+}}@foo4 -// CHECK2-SAME: () #[[ATTR1]] { +// CHECK2-LABEL: define dso_local void @foo4( +// CHECK2-SAME: ) #[[ATTR1]] { // CHECK2-NEXT: entry: // CHECK2-NEXT: [[DOTOMP_IV:%.*]] = alloca i32, align 4 // CHECK2-NEXT: [[TMP:%.*]] = alloca i32, align 4 @@ -1727,21 +2048,21 @@ extern "C" void foo8(int a) { // CHECK2-NEXT: [[TMP22:%.*]] = load i32, ptr [[DOTTILE_1_IV_J]], align 4 // CHECK2-NEXT: [[INC:%.*]] = add nsw i32 [[TMP22]], 1 // CHECK2-NEXT: store i32 [[INC]], ptr [[DOTTILE_1_IV_J]], align 4 -// CHECK2-NEXT: br label [[FOR_COND20]], !llvm.loop [[LOOP15:![0-9]+]] +// CHECK2-NEXT: br label [[FOR_COND20]], !llvm.loop [[LOOP17:![0-9]+]] // CHECK2: for.end: // CHECK2-NEXT: br label [[FOR_INC32:%.*]] // CHECK2: for.inc32: // CHECK2-NEXT: [[TMP23:%.*]] = load i32, ptr [[DOTTILE_0_IV_I]], align 4 // CHECK2-NEXT: [[INC33:%.*]] = add nsw i32 [[TMP23]], 1 // CHECK2-NEXT: store i32 [[INC33]], ptr [[DOTTILE_0_IV_I]], align 4 -// CHECK2-NEXT: br label [[FOR_COND8]], !llvm.loop [[LOOP16:![0-9]+]] +// CHECK2-NEXT: br label [[FOR_COND8]], !llvm.loop [[LOOP18:![0-9]+]] // CHECK2: for.end34: // CHECK2-NEXT: br label [[FOR_INC35:%.*]] // CHECK2: for.inc35: // CHECK2-NEXT: [[TMP24:%.*]] = load i32, ptr [[DOTFLOOR_1_IV_J]], align 4 // CHECK2-NEXT: [[ADD36:%.*]] = add nsw i32 [[TMP24]], 5 // CHECK2-NEXT: store i32 [[ADD36]], ptr [[DOTFLOOR_1_IV_J]], align 4 -// CHECK2-NEXT: br label [[FOR_COND]], !llvm.loop [[LOOP17:![0-9]+]] +// CHECK2-NEXT: br label [[FOR_COND]], !llvm.loop [[LOOP19:![0-9]+]] // CHECK2: for.end37: // CHECK2-NEXT: br label [[OMP_BODY_CONTINUE:%.*]] // CHECK2: omp.body.continue: @@ -1759,8 +2080,8 @@ extern "C" void foo8(int a) { // CHECK2-NEXT: ret void // // -// CHECK2-LABEL: define {{[^@]+}}@foo5 -// CHECK2-SAME: () #[[ATTR1]] { +// CHECK2-LABEL: define dso_local void @foo5( +// CHECK2-SAME: ) #[[ATTR1]] { // CHECK2-NEXT: entry: // CHECK2-NEXT: [[DOTOMP_IV:%.*]] = alloca i64, align 8 // CHECK2-NEXT: [[TMP:%.*]] = alloca i32, align 4 @@ -1968,15 +2289,15 @@ extern "C" void foo8(int a) { // CHECK2-NEXT: ret void // // -// CHECK2-LABEL: define {{[^@]+}}@foo6 -// CHECK2-SAME: () #[[ATTR1]] { +// CHECK2-LABEL: define dso_local void @foo6( +// CHECK2-SAME: ) #[[ATTR1]] { // CHECK2-NEXT: entry: // CHECK2-NEXT: call void (ptr, i32, ptr, ...) @__kmpc_fork_call(ptr @[[GLOB2]], i32 0, ptr @foo6.omp_outlined) // CHECK2-NEXT: ret void // // -// CHECK2-LABEL: define {{[^@]+}}@foo6.omp_outlined -// CHECK2-SAME: (ptr noalias noundef [[DOTGLOBAL_TID_:%.*]], ptr noalias noundef [[DOTBOUND_TID_:%.*]]) #[[ATTR4:[0-9]+]] { +// CHECK2-LABEL: define internal void @foo6.omp_outlined( +// CHECK2-SAME: ptr noalias noundef [[DOTGLOBAL_TID_:%.*]], ptr noalias noundef [[DOTBOUND_TID_:%.*]]) #[[ATTR4:[0-9]+]] { // CHECK2-NEXT: entry: // CHECK2-NEXT: [[DOTGLOBAL_TID__ADDR:%.*]] = alloca ptr, align 8 // CHECK2-NEXT: [[DOTBOUND_TID__ADDR:%.*]] = alloca ptr, align 8 @@ -2054,7 +2375,7 @@ extern "C" void foo8(int a) { // CHECK2-NEXT: [[TMP14:%.*]] = load i32, ptr [[DOTTILE_0_IV_I]], align 4 // CHECK2-NEXT: [[INC:%.*]] = add nsw i32 [[TMP14]], 1 // CHECK2-NEXT: store i32 [[INC]], ptr [[DOTTILE_0_IV_I]], align 4 -// CHECK2-NEXT: br label [[FOR_COND]], !llvm.loop [[LOOP18:![0-9]+]] +// CHECK2-NEXT: br label [[FOR_COND]], !llvm.loop [[LOOP20:![0-9]+]] // CHECK2: for.end: // CHECK2-NEXT: br label [[OMP_BODY_CONTINUE:%.*]] // CHECK2: omp.body.continue: @@ -2071,8 +2392,8 @@ extern "C" void foo8(int a) { // CHECK2-NEXT: ret void // // -// CHECK2-LABEL: define {{[^@]+}}@foo8 -// CHECK2-SAME: (i32 noundef [[A:%.*]]) #[[ATTR1]] { +// CHECK2-LABEL: define dso_local void @foo8( +// CHECK2-SAME: i32 noundef [[A:%.*]]) #[[ATTR1]] { // CHECK2-NEXT: entry: // CHECK2-NEXT: [[A_ADDR:%.*]] = alloca i32, align 4 // CHECK2-NEXT: [[I:%.*]] = alloca i32, align 4 @@ -2138,7 +2459,7 @@ extern "C" void foo8(int a) { // CHECK2-NEXT: [[TMP11:%.*]] = load i32, ptr [[DOTTILE_0_IV_I]], align 4 // CHECK2-NEXT: [[INC:%.*]] = add nsw i32 [[TMP11]], 1 // CHECK2-NEXT: store i32 [[INC]], ptr [[DOTTILE_0_IV_I]], align 4 -// CHECK2-NEXT: br label [[FOR_COND1]], !llvm.loop [[LOOP21:![0-9]+]] +// CHECK2-NEXT: br label [[FOR_COND1]], !llvm.loop [[LOOP23:![0-9]+]] // CHECK2: for.end: // CHECK2-NEXT: br label [[FOR_INC17:%.*]] // CHECK2: for.inc17: @@ -2155,20 +2476,117 @@ extern "C" void foo8(int a) { // CHECK2-NEXT: [[TMP14:%.*]] = load i32, ptr [[DOTFLOOR_0_IV_I]], align 4 // CHECK2-NEXT: [[ADD23:%.*]] = add nsw i32 [[TMP14]], [[COND22]] // CHECK2-NEXT: store i32 [[ADD23]], ptr [[DOTFLOOR_0_IV_I]], align 4 -// CHECK2-NEXT: br label [[FOR_COND]], !llvm.loop [[LOOP22:![0-9]+]] +// CHECK2-NEXT: br label [[FOR_COND]], !llvm.loop [[LOOP24:![0-9]+]] // CHECK2: for.end24: // CHECK2-NEXT: ret void // // -// CHECK2-LABEL: define {{[^@]+}}@tfoo7 -// CHECK2-SAME: () #[[ATTR1]] { +// CHECK2-LABEL: define dso_local void @foo9( +// CHECK2-SAME: ptr noundef byval([[STRUCT_DATA_T:%.*]]) align 8 [[DATA:%.*]]) #[[ATTR1]] { +// CHECK2-NEXT: entry: +// CHECK2-NEXT: [[__RANGE2:%.*]] = alloca ptr, align 8 +// CHECK2-NEXT: [[__END2:%.*]] = alloca ptr, align 8 +// CHECK2-NEXT: [[__BEGIN2:%.*]] = alloca ptr, align 8 +// CHECK2-NEXT: [[DOTCAPTURE_EXPR_:%.*]] = alloca ptr, align 8 +// CHECK2-NEXT: [[DOTCAPTURE_EXPR_3:%.*]] = alloca ptr, align 8 +// CHECK2-NEXT: [[DOTCAPTURE_EXPR_4:%.*]] = alloca i64, align 8 +// CHECK2-NEXT: [[DOTFLOOR_0_IV___BEGIN2:%.*]] = alloca i64, align 8 +// CHECK2-NEXT: [[DOTTILE_0_IV___BEGIN2:%.*]] = alloca i64, align 8 +// CHECK2-NEXT: [[V:%.*]] = alloca double, align 8 +// CHECK2-NEXT: [[ARRAY:%.*]] = getelementptr inbounds [[STRUCT_DATA_T]], ptr [[DATA]], i32 0, i32 0 +// CHECK2-NEXT: store ptr [[ARRAY]], ptr [[__RANGE2]], align 8 +// CHECK2-NEXT: [[TMP0:%.*]] = load ptr, ptr [[__RANGE2]], align 8 +// CHECK2-NEXT: [[ARRAYDECAY:%.*]] = getelementptr inbounds [12 x double], ptr [[TMP0]], i64 0, i64 0 +// CHECK2-NEXT: [[ADD_PTR:%.*]] = getelementptr inbounds double, ptr [[ARRAYDECAY]], i64 12 +// CHECK2-NEXT: store ptr [[ADD_PTR]], ptr [[__END2]], align 8 +// CHECK2-NEXT: [[TMP1:%.*]] = load ptr, ptr [[__RANGE2]], align 8 +// CHECK2-NEXT: [[ARRAYDECAY1:%.*]] = getelementptr inbounds [12 x double], ptr [[TMP1]], i64 0, i64 0 +// CHECK2-NEXT: store ptr [[ARRAYDECAY1]], ptr [[__BEGIN2]], align 8 +// CHECK2-NEXT: [[TMP2:%.*]] = load ptr, ptr [[__RANGE2]], align 8 +// CHECK2-NEXT: [[ARRAYDECAY2:%.*]] = getelementptr inbounds [12 x double], ptr [[TMP2]], i64 0, i64 0 +// CHECK2-NEXT: store ptr [[ARRAYDECAY2]], ptr [[DOTCAPTURE_EXPR_]], align 8 +// CHECK2-NEXT: [[TMP3:%.*]] = load ptr, ptr [[__END2]], align 8 +// CHECK2-NEXT: store ptr [[TMP3]], ptr [[DOTCAPTURE_EXPR_3]], align 8 +// CHECK2-NEXT: [[TMP4:%.*]] = load ptr, ptr [[DOTCAPTURE_EXPR_3]], align 8 +// CHECK2-NEXT: [[TMP5:%.*]] = load ptr, ptr [[DOTCAPTURE_EXPR_]], align 8 +// CHECK2-NEXT: [[SUB_PTR_LHS_CAST:%.*]] = ptrtoint ptr [[TMP4]] to i64 +// CHECK2-NEXT: [[SUB_PTR_RHS_CAST:%.*]] = ptrtoint ptr [[TMP5]] to i64 +// CHECK2-NEXT: [[SUB_PTR_SUB:%.*]] = sub i64 [[SUB_PTR_LHS_CAST]], [[SUB_PTR_RHS_CAST]] +// CHECK2-NEXT: [[SUB_PTR_DIV:%.*]] = sdiv exact i64 [[SUB_PTR_SUB]], 8 +// CHECK2-NEXT: [[SUB:%.*]] = sub nsw i64 [[SUB_PTR_DIV]], 1 +// CHECK2-NEXT: [[ADD:%.*]] = add nsw i64 [[SUB]], 1 +// CHECK2-NEXT: [[DIV:%.*]] = sdiv i64 [[ADD]], 1 +// CHECK2-NEXT: [[SUB5:%.*]] = sub nsw i64 [[DIV]], 1 +// CHECK2-NEXT: store i64 [[SUB5]], ptr [[DOTCAPTURE_EXPR_4]], align 8 +// CHECK2-NEXT: store i64 0, ptr [[DOTFLOOR_0_IV___BEGIN2]], align 8 +// CHECK2-NEXT: br label [[FOR_COND:%.*]] +// CHECK2: for.cond: +// CHECK2-NEXT: [[TMP6:%.*]] = load i64, ptr [[DOTFLOOR_0_IV___BEGIN2]], align 8 +// CHECK2-NEXT: [[TMP7:%.*]] = load i64, ptr [[DOTCAPTURE_EXPR_4]], align 8 +// CHECK2-NEXT: [[ADD6:%.*]] = add nsw i64 [[TMP7]], 1 +// CHECK2-NEXT: [[CMP:%.*]] = icmp slt i64 [[TMP6]], [[ADD6]] +// CHECK2-NEXT: br i1 [[CMP]], label [[FOR_BODY:%.*]], label [[FOR_END18:%.*]] +// CHECK2: for.body: +// CHECK2-NEXT: [[TMP8:%.*]] = load i64, ptr [[DOTFLOOR_0_IV___BEGIN2]], align 8 +// CHECK2-NEXT: store i64 [[TMP8]], ptr [[DOTTILE_0_IV___BEGIN2]], align 8 +// CHECK2-NEXT: br label [[FOR_COND7:%.*]] +// CHECK2: for.cond7: +// CHECK2-NEXT: [[TMP9:%.*]] = load i64, ptr [[DOTTILE_0_IV___BEGIN2]], align 8 +// CHECK2-NEXT: [[TMP10:%.*]] = load i64, ptr [[DOTCAPTURE_EXPR_4]], align 8 +// CHECK2-NEXT: [[ADD8:%.*]] = add nsw i64 [[TMP10]], 1 +// CHECK2-NEXT: [[TMP11:%.*]] = load i64, ptr [[DOTFLOOR_0_IV___BEGIN2]], align 8 +// CHECK2-NEXT: [[ADD9:%.*]] = add nsw i64 [[TMP11]], 5 +// CHECK2-NEXT: [[CMP10:%.*]] = icmp slt i64 [[ADD8]], [[ADD9]] +// CHECK2-NEXT: br i1 [[CMP10]], label [[COND_TRUE:%.*]], label [[COND_FALSE:%.*]] +// CHECK2: cond.true: +// CHECK2-NEXT: [[TMP12:%.*]] = load i64, ptr [[DOTCAPTURE_EXPR_4]], align 8 +// CHECK2-NEXT: [[ADD11:%.*]] = add nsw i64 [[TMP12]], 1 +// CHECK2-NEXT: br label [[COND_END:%.*]] +// CHECK2: cond.false: +// CHECK2-NEXT: [[TMP13:%.*]] = load i64, ptr [[DOTFLOOR_0_IV___BEGIN2]], align 8 +// CHECK2-NEXT: [[ADD12:%.*]] = add nsw i64 [[TMP13]], 5 +// CHECK2-NEXT: br label [[COND_END]] +// CHECK2: cond.end: +// CHECK2-NEXT: [[COND:%.*]] = phi i64 [ [[ADD11]], [[COND_TRUE]] ], [ [[ADD12]], [[COND_FALSE]] ] +// CHECK2-NEXT: [[CMP13:%.*]] = icmp slt i64 [[TMP9]], [[COND]] +// CHECK2-NEXT: br i1 [[CMP13]], label [[FOR_BODY14:%.*]], label [[FOR_END:%.*]] +// CHECK2: for.body14: +// CHECK2-NEXT: [[TMP14:%.*]] = load ptr, ptr [[DOTCAPTURE_EXPR_]], align 8 +// CHECK2-NEXT: [[TMP15:%.*]] = load i64, ptr [[DOTTILE_0_IV___BEGIN2]], align 8 +// CHECK2-NEXT: [[MUL:%.*]] = mul nsw i64 [[TMP15]], 1 +// CHECK2-NEXT: [[ADD_PTR15:%.*]] = getelementptr inbounds double, ptr [[TMP14]], i64 [[MUL]] +// CHECK2-NEXT: store ptr [[ADD_PTR15]], ptr [[__BEGIN2]], align 8 +// CHECK2-NEXT: [[TMP16:%.*]] = load ptr, ptr [[__BEGIN2]], align 8 +// CHECK2-NEXT: [[TMP17:%.*]] = load double, ptr [[TMP16]], align 8 +// CHECK2-NEXT: store double [[TMP17]], ptr [[V]], align 8 +// CHECK2-NEXT: [[TMP18:%.*]] = load double, ptr [[V]], align 8 +// CHECK2-NEXT: call void (...) @body(double noundef [[TMP18]]) +// CHECK2-NEXT: br label [[FOR_INC:%.*]] +// CHECK2: for.inc: +// CHECK2-NEXT: [[TMP19:%.*]] = load i64, ptr [[DOTTILE_0_IV___BEGIN2]], align 8 +// CHECK2-NEXT: [[INC:%.*]] = add nsw i64 [[TMP19]], 1 +// CHECK2-NEXT: store i64 [[INC]], ptr [[DOTTILE_0_IV___BEGIN2]], align 8 +// CHECK2-NEXT: br label [[FOR_COND7]], !llvm.loop [[LOOP25:![0-9]+]] +// CHECK2: for.end: +// CHECK2-NEXT: br label [[FOR_INC16:%.*]] +// CHECK2: for.inc16: +// CHECK2-NEXT: [[TMP20:%.*]] = load i64, ptr [[DOTFLOOR_0_IV___BEGIN2]], align 8 +// CHECK2-NEXT: [[ADD17:%.*]] = add nsw i64 [[TMP20]], 5 +// CHECK2-NEXT: store i64 [[ADD17]], ptr [[DOTFLOOR_0_IV___BEGIN2]], align 8 +// CHECK2-NEXT: br label [[FOR_COND]], !llvm.loop [[LOOP26:![0-9]+]] +// CHECK2: for.end18: +// CHECK2-NEXT: ret void +// +// +// CHECK2-LABEL: define dso_local void @tfoo7( +// CHECK2-SAME: ) #[[ATTR1]] { // CHECK2-NEXT: entry: // CHECK2-NEXT: call void @_Z4foo7IiTnT_Li3ETnS0_Li5EEvS0_S0_(i32 noundef 0, i32 noundef 42) // CHECK2-NEXT: ret void // // -// CHECK2-LABEL: define {{[^@]+}}@_Z4foo7IiTnT_Li3ETnS0_Li5EEvS0_S0_ -// CHECK2-SAME: (i32 noundef [[START:%.*]], i32 noundef [[END:%.*]]) #[[ATTR1]] comdat { +// CHECK2-LABEL: define linkonce_odr void @_Z4foo7IiTnT_Li3ETnS0_Li5EEvS0_S0_( +// CHECK2-SAME: i32 noundef [[START:%.*]], i32 noundef [[END:%.*]]) #[[ATTR1]] comdat { // CHECK2-NEXT: entry: // CHECK2-NEXT: [[START_ADDR:%.*]] = alloca i32, align 4 // CHECK2-NEXT: [[END_ADDR:%.*]] = alloca i32, align 4 @@ -2211,7 +2629,7 @@ extern "C" void foo8(int a) { // CHECK2-NEXT: [[TMP9:%.*]] = load i32, ptr [[DOTCAPTURE_EXPR_2]], align 4 // CHECK2-NEXT: [[ADD7:%.*]] = add i32 [[TMP9]], 1 // CHECK2-NEXT: [[TMP10:%.*]] = load i32, ptr [[DOTFLOOR_0_IV_I]], align 4 -// CHECK2-NEXT: [[ADD8:%.*]] = add nsw i32 [[TMP10]], 5 +// CHECK2-NEXT: [[ADD8:%.*]] = add i32 [[TMP10]], 5 // CHECK2-NEXT: [[CMP9:%.*]] = icmp ult i32 [[ADD7]], [[ADD8]] // CHECK2-NEXT: br i1 [[CMP9]], label [[COND_TRUE:%.*]], label [[COND_FALSE:%.*]] // CHECK2: cond.true: @@ -2220,7 +2638,7 @@ extern "C" void foo8(int a) { // CHECK2-NEXT: br label [[COND_END:%.*]] // CHECK2: cond.false: // CHECK2-NEXT: [[TMP12:%.*]] = load i32, ptr [[DOTFLOOR_0_IV_I]], align 4 -// CHECK2-NEXT: [[ADD11:%.*]] = add nsw i32 [[TMP12]], 5 +// CHECK2-NEXT: [[ADD11:%.*]] = add i32 [[TMP12]], 5 // CHECK2-NEXT: br label [[COND_END]] // CHECK2: cond.end: // CHECK2-NEXT: [[COND:%.*]] = phi i32 [ [[ADD10]], [[COND_TRUE]] ], [ [[ADD11]], [[COND_FALSE]] ] @@ -2237,23 +2655,74 @@ extern "C" void foo8(int a) { // CHECK2-NEXT: br label [[FOR_INC:%.*]] // CHECK2: for.inc: // CHECK2-NEXT: [[TMP16:%.*]] = load i32, ptr [[DOTTILE_0_IV_I]], align 4 -// CHECK2-NEXT: [[INC:%.*]] = add nsw i32 [[TMP16]], 1 +// CHECK2-NEXT: [[INC:%.*]] = add i32 [[TMP16]], 1 // CHECK2-NEXT: store i32 [[INC]], ptr [[DOTTILE_0_IV_I]], align 4 -// CHECK2-NEXT: br label [[FOR_COND6]], !llvm.loop [[LOOP23:![0-9]+]] +// CHECK2-NEXT: br label [[FOR_COND6]], !llvm.loop [[LOOP27:![0-9]+]] // CHECK2: for.end: // CHECK2-NEXT: br label [[FOR_INC15:%.*]] // CHECK2: for.inc15: // CHECK2-NEXT: [[TMP17:%.*]] = load i32, ptr [[DOTFLOOR_0_IV_I]], align 4 -// CHECK2-NEXT: [[ADD16:%.*]] = add nsw i32 [[TMP17]], 5 +// CHECK2-NEXT: [[ADD16:%.*]] = add i32 [[TMP17]], 5 // CHECK2-NEXT: store i32 [[ADD16]], ptr [[DOTFLOOR_0_IV_I]], align 4 -// CHECK2-NEXT: br label [[FOR_COND]], !llvm.loop [[LOOP24:![0-9]+]] +// CHECK2-NEXT: br label [[FOR_COND]], !llvm.loop [[LOOP28:![0-9]+]] // CHECK2: for.end17: // CHECK2-NEXT: ret void // // -// CHECK2-LABEL: define {{[^@]+}}@_GLOBAL__sub_I_tile_codegen.cpp -// CHECK2-SAME: () #[[ATTR0]] section ".text.startup" { +// CHECK2-LABEL: define internal void @_GLOBAL__sub_I_tile_codegen.cpp( +// CHECK2-SAME: ) #[[ATTR0]] section ".text.startup" { // CHECK2-NEXT: entry: // CHECK2-NEXT: call void @__cxx_global_var_init() // CHECK2-NEXT: ret void // +//. +// CHECK1: [[LOOP3]] = distinct !{[[LOOP3]], [[META4:![0-9]+]]} +// CHECK1: [[META4]] = !{!"llvm.loop.mustprogress"} +// CHECK1: [[LOOP5]] = distinct !{[[LOOP5]], [[META4]]} +// CHECK1: [[LOOP6]] = distinct !{[[LOOP6]], [[META4]]} +// CHECK1: [[LOOP7]] = distinct !{[[LOOP7]], [[META4]]} +// CHECK1: [[LOOP8]] = distinct !{[[LOOP8]], [[META4]]} +// CHECK1: [[LOOP9]] = distinct !{[[LOOP9]], [[META4]]} +// CHECK1: [[LOOP10]] = distinct !{[[LOOP10]], [[META4]]} +// CHECK1: [[LOOP11]] = distinct !{[[LOOP11]], [[META4]]} +// CHECK1: [[LOOP12]] = distinct !{[[LOOP12]], [[META4]]} +// CHECK1: [[LOOP13]] = distinct !{[[LOOP13]], [[META4]]} +// CHECK1: [[LOOP14]] = distinct !{[[LOOP14]], [[META4]]} +// CHECK1: [[LOOP15]] = distinct !{[[LOOP15]], [[META4]]} +// CHECK1: [[LOOP16]] = distinct !{[[LOOP16]], [[META4]]} +// CHECK1: [[LOOP17]] = distinct !{[[LOOP17]], [[META4]]} +// CHECK1: [[LOOP18]] = distinct !{[[LOOP18]], [[META4]]} +// CHECK1: [[LOOP21]] = distinct !{[[LOOP21]], [[META4]]} +// CHECK1: [[LOOP22]] = distinct !{[[LOOP22]], [[META4]]} +// CHECK1: [[LOOP23]] = distinct !{[[LOOP23]], [[META4]]} +// CHECK1: [[LOOP24]] = distinct !{[[LOOP24]], [[META4]]} +// CHECK1: [[LOOP25]] = distinct !{[[LOOP25]], [[META4]]} +// CHECK1: [[LOOP26]] = distinct !{[[LOOP26]], [[META4]]} +// CHECK1: [[LOOP27]] = distinct !{[[LOOP27]], [[META4]]} +// CHECK1: [[LOOP28]] = distinct !{[[LOOP28]], [[META4]]} +//. +// CHECK2: [[LOOP3]] = distinct !{[[LOOP3]], [[META4:![0-9]+]]} +// CHECK2: [[META4]] = !{!"llvm.loop.mustprogress"} +// CHECK2: [[LOOP5]] = distinct !{[[LOOP5]], [[META4]]} +// CHECK2: [[LOOP6]] = distinct !{[[LOOP6]], [[META4]]} +// CHECK2: [[LOOP7]] = distinct !{[[LOOP7]], [[META4]]} +// CHECK2: [[LOOP8]] = distinct !{[[LOOP8]], [[META4]]} +// CHECK2: [[LOOP9]] = distinct !{[[LOOP9]], [[META4]]} +// CHECK2: [[LOOP10]] = distinct !{[[LOOP10]], [[META4]]} +// CHECK2: [[LOOP11]] = distinct !{[[LOOP11]], [[META4]]} +// CHECK2: [[LOOP12]] = distinct !{[[LOOP12]], [[META4]]} +// CHECK2: [[LOOP13]] = distinct !{[[LOOP13]], [[META4]]} +// CHECK2: [[LOOP14]] = distinct !{[[LOOP14]], [[META4]]} +// CHECK2: [[LOOP15]] = distinct !{[[LOOP15]], [[META4]]} +// CHECK2: [[LOOP16]] = distinct !{[[LOOP16]], [[META4]]} +// CHECK2: [[LOOP17]] = distinct !{[[LOOP17]], [[META4]]} +// CHECK2: [[LOOP18]] = distinct !{[[LOOP18]], [[META4]]} +// CHECK2: [[LOOP19]] = distinct !{[[LOOP19]], [[META4]]} +// CHECK2: [[LOOP20]] = distinct !{[[LOOP20]], [[META4]]} +// CHECK2: [[LOOP23]] = distinct !{[[LOOP23]], [[META4]]} +// CHECK2: [[LOOP24]] = distinct !{[[LOOP24]], [[META4]]} +// CHECK2: [[LOOP25]] = distinct !{[[LOOP25]], [[META4]]} +// CHECK2: [[LOOP26]] = distinct !{[[LOOP26]], [[META4]]} +// CHECK2: [[LOOP27]] = distinct !{[[LOOP27]], [[META4]]} +// CHECK2: [[LOOP28]] = distinct !{[[LOOP28]], [[META4]]} +//. diff --git a/clang/test/OpenMP/tile_codegen_for_dependent.cpp b/clang/test/OpenMP/tile_codegen_for_dependent.cpp index 93c51c9165a4..820d33d15287 100644 --- a/clang/test/OpenMP/tile_codegen_for_dependent.cpp +++ b/clang/test/OpenMP/tile_codegen_for_dependent.cpp @@ -17,7 +17,7 @@ extern "C" void body(...) {} -// IR-LABEL: @func( +// IR-LABEL: define {{.*}}@func( // IR-NEXT: [[ENTRY:.*]]: // IR-NEXT: %[[START_ADDR:.+]] = alloca i32, align 4 // IR-NEXT: %[[END_ADDR:.+]] = alloca i32, align 4 @@ -27,18 +27,18 @@ extern "C" void body(...) {} // IR-NEXT: %[[I:.+]] = alloca i32, align 4 // IR-NEXT: %[[DOTCAPTURE_EXPR_:.+]] = alloca i32, align 4 // IR-NEXT: %[[DOTCAPTURE_EXPR_1:.+]] = alloca i32, align 4 +// IR-NEXT: %[[DOTNEW_STEP:.+]] = alloca i32, align 4 // IR-NEXT: %[[DOTCAPTURE_EXPR_2:.+]] = alloca i32, align 4 -// IR-NEXT: %[[DOTCAPTURE_EXPR_3:.+]] = alloca i32, align 4 -// IR-NEXT: %[[DOTCAPTURE_EXPR_6:.+]] = alloca i32, align 4 -// IR-NEXT: %[[DOTCAPTURE_EXPR_8:.+]] = alloca i32, align 4 +// IR-NEXT: %[[DOTCAPTURE_EXPR_5:.+]] = alloca i32, align 4 +// IR-NEXT: %[[DOTCAPTURE_EXPR_7:.+]] = alloca i32, align 4 // IR-NEXT: %[[DOTFLOOR_0_IV_I:.+]] = alloca i32, align 4 // IR-NEXT: %[[DOTOMP_LB:.+]] = alloca i32, align 4 // IR-NEXT: %[[DOTOMP_UB:.+]] = alloca i32, align 4 // IR-NEXT: %[[DOTOMP_STRIDE:.+]] = alloca i32, align 4 // IR-NEXT: %[[DOTOMP_IS_LAST:.+]] = alloca i32, align 4 -// IR-NEXT: %[[DOTFLOOR_0_IV_I12:.+]] = alloca i32, align 4 +// IR-NEXT: %[[DOTFLOOR_0_IV_I11:.+]] = alloca i32, align 4 // IR-NEXT: %[[DOTTILE_0_IV_I:.+]] = alloca i32, align 4 -// IR-NEXT: %[[TMP0:.+]] = call i32 @__kmpc_global_thread_num(ptr @2) +// IR-NEXT: %[[TMP0:.+]] = call i32 @__kmpc_global_thread_num(ptr @[[GLOB2:.+]]) // IR-NEXT: store i32 %[[START:.+]], ptr %[[START_ADDR]], align 4 // IR-NEXT: store i32 %[[END:.+]], ptr %[[END_ADDR]], align 4 // IR-NEXT: store i32 %[[STEP:.+]], ptr %[[STEP_ADDR]], align 4 @@ -49,44 +49,44 @@ extern "C" void body(...) {} // IR-NEXT: %[[TMP3:.+]] = load i32, ptr %[[END_ADDR]], align 4 // IR-NEXT: store i32 %[[TMP3]], ptr %[[DOTCAPTURE_EXPR_1]], align 4 // IR-NEXT: %[[TMP4:.+]] = load i32, ptr %[[STEP_ADDR]], align 4 -// IR-NEXT: store i32 %[[TMP4]], ptr %[[DOTCAPTURE_EXPR_2]], align 4 +// IR-NEXT: store i32 %[[TMP4]], ptr %[[DOTNEW_STEP]], align 4 // IR-NEXT: %[[TMP5:.+]] = load i32, ptr %[[DOTCAPTURE_EXPR_1]], align 4 // IR-NEXT: %[[TMP6:.+]] = load i32, ptr %[[DOTCAPTURE_EXPR_]], align 4 // IR-NEXT: %[[SUB:.+]] = sub i32 %[[TMP5]], %[[TMP6]] -// IR-NEXT: %[[SUB4:.+]] = sub i32 %[[SUB]], 1 -// IR-NEXT: %[[TMP7:.+]] = load i32, ptr %[[DOTCAPTURE_EXPR_2]], align 4 -// IR-NEXT: %[[ADD:.+]] = add i32 %[[SUB4]], %[[TMP7]] -// IR-NEXT: %[[TMP8:.+]] = load i32, ptr %[[DOTCAPTURE_EXPR_2]], align 4 +// IR-NEXT: %[[SUB3:.+]] = sub i32 %[[SUB]], 1 +// IR-NEXT: %[[TMP7:.+]] = load i32, ptr %[[DOTNEW_STEP]], align 4 +// IR-NEXT: %[[ADD:.+]] = add i32 %[[SUB3]], %[[TMP7]] +// IR-NEXT: %[[TMP8:.+]] = load i32, ptr %[[DOTNEW_STEP]], align 4 // IR-NEXT: %[[DIV:.+]] = udiv i32 %[[ADD]], %[[TMP8]] -// IR-NEXT: %[[SUB5:.+]] = sub i32 %[[DIV]], 1 -// IR-NEXT: store i32 %[[SUB5]], ptr %[[DOTCAPTURE_EXPR_3]], align 4 -// IR-NEXT: %[[TMP9:.+]] = load i32, ptr %[[DOTCAPTURE_EXPR_3]], align 4 -// IR-NEXT: %[[ADD7:.+]] = add i32 %[[TMP9]], 1 -// IR-NEXT: store i32 %[[ADD7]], ptr %[[DOTCAPTURE_EXPR_6]], align 4 -// IR-NEXT: %[[TMP10:.+]] = load i32, ptr %[[DOTCAPTURE_EXPR_6]], align 4 -// IR-NEXT: %[[SUB9:.+]] = sub i32 %[[TMP10]], -3 -// IR-NEXT: %[[DIV10:.+]] = udiv i32 %[[SUB9]], 4 -// IR-NEXT: %[[SUB11:.+]] = sub i32 %[[DIV10]], 1 -// IR-NEXT: store i32 %[[SUB11]], ptr %[[DOTCAPTURE_EXPR_8]], align 4 +// IR-NEXT: %[[SUB4:.+]] = sub i32 %[[DIV]], 1 +// IR-NEXT: store i32 %[[SUB4]], ptr %[[DOTCAPTURE_EXPR_2]], align 4 +// IR-NEXT: %[[TMP9:.+]] = load i32, ptr %[[DOTCAPTURE_EXPR_2]], align 4 +// IR-NEXT: %[[ADD6:.+]] = add i32 %[[TMP9]], 1 +// IR-NEXT: store i32 %[[ADD6]], ptr %[[DOTCAPTURE_EXPR_5]], align 4 +// IR-NEXT: %[[TMP10:.+]] = load i32, ptr %[[DOTCAPTURE_EXPR_5]], align 4 +// IR-NEXT: %[[SUB8:.+]] = sub i32 %[[TMP10]], -3 +// IR-NEXT: %[[DIV9:.+]] = udiv i32 %[[SUB8]], 4 +// IR-NEXT: %[[SUB10:.+]] = sub i32 %[[DIV9]], 1 +// IR-NEXT: store i32 %[[SUB10]], ptr %[[DOTCAPTURE_EXPR_7]], align 4 // IR-NEXT: store i32 0, ptr %[[DOTFLOOR_0_IV_I]], align 4 -// IR-NEXT: %[[TMP11:.+]] = load i32, ptr %[[DOTCAPTURE_EXPR_6]], align 4 +// IR-NEXT: %[[TMP11:.+]] = load i32, ptr %[[DOTCAPTURE_EXPR_5]], align 4 // IR-NEXT: %[[CMP:.+]] = icmp ult i32 0, %[[TMP11]] // IR-NEXT: br i1 %[[CMP]], label %[[OMP_PRECOND_THEN:.+]], label %[[OMP_PRECOND_END:.+]] // IR-EMPTY: // IR-NEXT: [[OMP_PRECOND_THEN]]: // IR-NEXT: store i32 0, ptr %[[DOTOMP_LB]], align 4 -// IR-NEXT: %[[TMP12:.+]] = load i32, ptr %[[DOTCAPTURE_EXPR_8]], align 4 +// IR-NEXT: %[[TMP12:.+]] = load i32, ptr %[[DOTCAPTURE_EXPR_7]], align 4 // IR-NEXT: store i32 %[[TMP12]], ptr %[[DOTOMP_UB]], align 4 // IR-NEXT: store i32 1, ptr %[[DOTOMP_STRIDE]], align 4 // IR-NEXT: store i32 0, ptr %[[DOTOMP_IS_LAST]], align 4 -// IR-NEXT: call void @__kmpc_for_static_init_4u(ptr @1, i32 %[[TMP0]], i32 34, ptr %[[DOTOMP_IS_LAST]], ptr %[[DOTOMP_LB]], ptr %[[DOTOMP_UB]], ptr %[[DOTOMP_STRIDE]], i32 1, i32 1) +// IR-NEXT: call void @__kmpc_for_static_init_4u(ptr @[[GLOB1:.+]], i32 %[[TMP0]], i32 34, ptr %[[DOTOMP_IS_LAST]], ptr %[[DOTOMP_LB]], ptr %[[DOTOMP_UB]], ptr %[[DOTOMP_STRIDE]], i32 1, i32 1) // IR-NEXT: %[[TMP13:.+]] = load i32, ptr %[[DOTOMP_UB]], align 4 -// IR-NEXT: %[[TMP14:.+]] = load i32, ptr %[[DOTCAPTURE_EXPR_8]], align 4 -// IR-NEXT: %[[CMP13:.+]] = icmp ugt i32 %[[TMP13]], %[[TMP14]] -// IR-NEXT: br i1 %[[CMP13]], label %[[COND_TRUE:.+]], label %[[COND_FALSE:.+]] +// IR-NEXT: %[[TMP14:.+]] = load i32, ptr %[[DOTCAPTURE_EXPR_7]], align 4 +// IR-NEXT: %[[CMP12:.+]] = icmp ugt i32 %[[TMP13]], %[[TMP14]] +// IR-NEXT: br i1 %[[CMP12]], label %[[COND_TRUE:.+]], label %[[COND_FALSE:.+]] // IR-EMPTY: // IR-NEXT: [[COND_TRUE]]: -// IR-NEXT: %[[TMP15:.+]] = load i32, ptr %[[DOTCAPTURE_EXPR_8]], align 4 +// IR-NEXT: %[[TMP15:.+]] = load i32, ptr %[[DOTCAPTURE_EXPR_7]], align 4 // IR-NEXT: br label %[[COND_END:.+]] // IR-EMPTY: // IR-NEXT: [[COND_FALSE]]: @@ -103,50 +103,50 @@ extern "C" void body(...) {} // IR-NEXT: [[OMP_INNER_FOR_COND]]: // IR-NEXT: %[[TMP18:.+]] = load i32, ptr %[[DOTOMP_IV]], align 4 // IR-NEXT: %[[TMP19:.+]] = load i32, ptr %[[DOTOMP_UB]], align 4 -// IR-NEXT: %[[ADD14:.+]] = add i32 %[[TMP19]], 1 -// IR-NEXT: %[[CMP15:.+]] = icmp ult i32 %[[TMP18]], %[[ADD14]] -// IR-NEXT: br i1 %[[CMP15]], label %[[OMP_INNER_FOR_BODY:.+]], label %[[OMP_INNER_FOR_END:.+]] +// IR-NEXT: %[[ADD13:.+]] = add i32 %[[TMP19]], 1 +// IR-NEXT: %[[CMP14:.+]] = icmp ult i32 %[[TMP18]], %[[ADD13]] +// IR-NEXT: br i1 %[[CMP14]], label %[[OMP_INNER_FOR_BODY:.+]], label %[[OMP_INNER_FOR_END:.+]] // IR-EMPTY: // IR-NEXT: [[OMP_INNER_FOR_BODY]]: // IR-NEXT: %[[TMP20:.+]] = load i32, ptr %[[DOTOMP_IV]], align 4 // IR-NEXT: %[[MUL:.+]] = mul i32 %[[TMP20]], 4 -// IR-NEXT: %[[ADD16:.+]] = add i32 0, %[[MUL]] -// IR-NEXT: store i32 %[[ADD16]], ptr %[[DOTFLOOR_0_IV_I12]], align 4 -// IR-NEXT: %[[TMP21:.+]] = load i32, ptr %[[DOTFLOOR_0_IV_I12]], align 4 +// IR-NEXT: %[[ADD15:.+]] = add i32 0, %[[MUL]] +// IR-NEXT: store i32 %[[ADD15]], ptr %[[DOTFLOOR_0_IV_I11]], align 4 +// IR-NEXT: %[[TMP21:.+]] = load i32, ptr %[[DOTFLOOR_0_IV_I11]], align 4 // IR-NEXT: store i32 %[[TMP21]], ptr %[[DOTTILE_0_IV_I]], align 4 // IR-NEXT: br label %[[FOR_COND:.+]] // IR-EMPTY: // IR-NEXT: [[FOR_COND]]: // IR-NEXT: %[[TMP22:.+]] = load i32, ptr %[[DOTTILE_0_IV_I]], align 4 -// IR-NEXT: %[[TMP23:.+]] = load i32, ptr %[[DOTCAPTURE_EXPR_3]], align 4 -// IR-NEXT: %[[ADD17:.+]] = add i32 %[[TMP23]], 1 -// IR-NEXT: %[[TMP24:.+]] = load i32, ptr %[[DOTFLOOR_0_IV_I12]], align 4 -// IR-NEXT: %[[ADD18:.+]] = add nsw i32 %[[TMP24]], 4 -// IR-NEXT: %[[CMP19:.+]] = icmp ult i32 %[[ADD17]], %[[ADD18]] -// IR-NEXT: br i1 %[[CMP19]], label %[[COND_TRUE20:.+]], label %[[COND_FALSE22:.+]] -// IR-EMPTY: -// IR-NEXT: [[COND_TRUE20]]: -// IR-NEXT: %[[TMP25:.+]] = load i32, ptr %[[DOTCAPTURE_EXPR_3]], align 4 -// IR-NEXT: %[[ADD21:.+]] = add i32 %[[TMP25]], 1 -// IR-NEXT: br label %[[COND_END24:.+]] -// IR-EMPTY: -// IR-NEXT: [[COND_FALSE22]]: -// IR-NEXT: %[[TMP26:.+]] = load i32, ptr %[[DOTFLOOR_0_IV_I12]], align 4 -// IR-NEXT: %[[ADD23:.+]] = add nsw i32 %[[TMP26]], 4 -// IR-NEXT: br label %[[COND_END24]] -// IR-EMPTY: -// IR-NEXT: [[COND_END24]]: -// IR-NEXT: %[[COND25:.+]] = phi i32 [ %[[ADD21]], %[[COND_TRUE20]] ], [ %[[ADD23]], %[[COND_FALSE22]] ] -// IR-NEXT: %[[CMP26:.+]] = icmp ult i32 %[[TMP22]], %[[COND25]] -// IR-NEXT: br i1 %[[CMP26]], label %[[FOR_BODY:.+]], label %[[FOR_END:.+]] +// IR-NEXT: %[[TMP23:.+]] = load i32, ptr %[[DOTCAPTURE_EXPR_2]], align 4 +// IR-NEXT: %[[ADD16:.+]] = add i32 %[[TMP23]], 1 +// IR-NEXT: %[[TMP24:.+]] = load i32, ptr %[[DOTFLOOR_0_IV_I11]], align 4 +// IR-NEXT: %[[ADD17:.+]] = add i32 %[[TMP24]], 4 +// IR-NEXT: %[[CMP18:.+]] = icmp ult i32 %[[ADD16]], %[[ADD17]] +// IR-NEXT: br i1 %[[CMP18]], label %[[COND_TRUE19:.+]], label %[[COND_FALSE21:.+]] +// IR-EMPTY: +// IR-NEXT: [[COND_TRUE19]]: +// IR-NEXT: %[[TMP25:.+]] = load i32, ptr %[[DOTCAPTURE_EXPR_2]], align 4 +// IR-NEXT: %[[ADD20:.+]] = add i32 %[[TMP25]], 1 +// IR-NEXT: br label %[[COND_END23:.+]] +// IR-EMPTY: +// IR-NEXT: [[COND_FALSE21]]: +// IR-NEXT: %[[TMP26:.+]] = load i32, ptr %[[DOTFLOOR_0_IV_I11]], align 4 +// IR-NEXT: %[[ADD22:.+]] = add i32 %[[TMP26]], 4 +// IR-NEXT: br label %[[COND_END23]] +// IR-EMPTY: +// IR-NEXT: [[COND_END23]]: +// IR-NEXT: %[[COND24:.+]] = phi i32 [ %[[ADD20]], %[[COND_TRUE19]] ], [ %[[ADD22]], %[[COND_FALSE21]] ] +// IR-NEXT: %[[CMP25:.+]] = icmp ult i32 %[[TMP22]], %[[COND24]] +// IR-NEXT: br i1 %[[CMP25]], label %[[FOR_BODY:.+]], label %[[FOR_END:.+]] // IR-EMPTY: // IR-NEXT: [[FOR_BODY]]: // IR-NEXT: %[[TMP27:.+]] = load i32, ptr %[[DOTCAPTURE_EXPR_]], align 4 // IR-NEXT: %[[TMP28:.+]] = load i32, ptr %[[DOTTILE_0_IV_I]], align 4 -// IR-NEXT: %[[TMP29:.+]] = load i32, ptr %[[DOTCAPTURE_EXPR_2]], align 4 -// IR-NEXT: %[[MUL27:.+]] = mul i32 %[[TMP28]], %[[TMP29]] -// IR-NEXT: %[[ADD28:.+]] = add i32 %[[TMP27]], %[[MUL27]] -// IR-NEXT: store i32 %[[ADD28]], ptr %[[I]], align 4 +// IR-NEXT: %[[TMP29:.+]] = load i32, ptr %[[DOTNEW_STEP]], align 4 +// IR-NEXT: %[[MUL26:.+]] = mul i32 %[[TMP28]], %[[TMP29]] +// IR-NEXT: %[[ADD27:.+]] = add i32 %[[TMP27]], %[[MUL26]] +// IR-NEXT: store i32 %[[ADD27]], ptr %[[I]], align 4 // IR-NEXT: %[[TMP30:.+]] = load i32, ptr %[[START_ADDR]], align 4 // IR-NEXT: %[[TMP31:.+]] = load i32, ptr %[[END_ADDR]], align 4 // IR-NEXT: %[[TMP32:.+]] = load i32, ptr %[[STEP_ADDR]], align 4 @@ -156,9 +156,9 @@ extern "C" void body(...) {} // IR-EMPTY: // IR-NEXT: [[FOR_INC]]: // IR-NEXT: %[[TMP34:.+]] = load i32, ptr %[[DOTTILE_0_IV_I]], align 4 -// IR-NEXT: %[[INC:.+]] = add nsw i32 %[[TMP34]], 1 +// IR-NEXT: %[[INC:.+]] = add i32 %[[TMP34]], 1 // IR-NEXT: store i32 %[[INC]], ptr %[[DOTTILE_0_IV_I]], align 4 -// IR-NEXT: br label %[[FOR_COND]], !llvm.loop ![[LOOP2:[0-9]+]] +// IR-NEXT: br label %[[FOR_COND]], !llvm.loop ![[LOOP3:[0-9]+]] // IR-EMPTY: // IR-NEXT: [[FOR_END]]: // IR-NEXT: br label %[[OMP_BODY_CONTINUE:.+]] @@ -168,19 +168,19 @@ extern "C" void body(...) {} // IR-EMPTY: // IR-NEXT: [[OMP_INNER_FOR_INC]]: // IR-NEXT: %[[TMP35:.+]] = load i32, ptr %[[DOTOMP_IV]], align 4 -// IR-NEXT: %[[ADD29:.+]] = add i32 %[[TMP35]], 1 -// IR-NEXT: store i32 %[[ADD29]], ptr %[[DOTOMP_IV]], align 4 +// IR-NEXT: %[[ADD28:.+]] = add i32 %[[TMP35]], 1 +// IR-NEXT: store i32 %[[ADD28]], ptr %[[DOTOMP_IV]], align 4 // IR-NEXT: br label %[[OMP_INNER_FOR_COND]] // IR-EMPTY: // IR-NEXT: [[OMP_INNER_FOR_END]]: // IR-NEXT: br label %[[OMP_LOOP_EXIT:.+]] // IR-EMPTY: // IR-NEXT: [[OMP_LOOP_EXIT]]: -// IR-NEXT: call void @__kmpc_for_static_fini(ptr @1, i32 %[[TMP0]]) +// IR-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 %[[TMP0]]) // IR-NEXT: br label %[[OMP_PRECOND_END]] // IR-EMPTY: // IR-NEXT: [[OMP_PRECOND_END]]: -// IR-NEXT: call void @__kmpc_barrier(ptr @3, i32 %[[TMP0]]) +// IR-NEXT: call void @__kmpc_barrier(ptr @[[GLOB3:.+]], i32 %[[TMP0]]) // IR-NEXT: ret void // IR-NEXT: } extern "C" void func(int start, int end, int step) { diff --git a/clang/test/OpenMP/tile_codegen_tile_for.cpp b/clang/test/OpenMP/tile_codegen_tile_for.cpp index d0fb89398c24..91536c406368 100644 --- a/clang/test/OpenMP/tile_codegen_tile_for.cpp +++ b/clang/test/OpenMP/tile_codegen_tile_for.cpp @@ -16,7 +16,7 @@ extern "C" void body(...) {} -// IR-LABEL: @func( +// IR-LABEL: define {{.*}}@func( // IR-NEXT: [[ENTRY:.*]]: // IR-NEXT: %[[START_ADDR:.+]] = alloca i32, align 4 // IR-NEXT: %[[END_ADDR:.+]] = alloca i32, align 4 @@ -26,22 +26,22 @@ extern "C" void body(...) {} // IR-NEXT: %[[I:.+]] = alloca i32, align 4 // IR-NEXT: %[[DOTCAPTURE_EXPR_:.+]] = alloca i32, align 4 // IR-NEXT: %[[DOTCAPTURE_EXPR_1:.+]] = alloca i32, align 4 +// IR-NEXT: %[[DOTNEW_STEP:.+]] = alloca i32, align 4 // IR-NEXT: %[[DOTCAPTURE_EXPR_2:.+]] = alloca i32, align 4 -// IR-NEXT: %[[DOTCAPTURE_EXPR_3:.+]] = alloca i32, align 4 // IR-NEXT: %[[DOTFLOOR_0_IV_I:.+]] = alloca i32, align 4 -// IR-NEXT: %[[DOTCAPTURE_EXPR_6:.+]] = alloca i32, align 4 -// IR-NEXT: %[[DOTCAPTURE_EXPR_8:.+]] = alloca i32, align 4 -// IR-NEXT: %[[DOTCAPTURE_EXPR_12:.+]] = alloca i32, align 4 -// IR-NEXT: %[[DOTCAPTURE_EXPR_14:.+]] = alloca i32, align 4 +// IR-NEXT: %[[DOTCAPTURE_EXPR_5:.+]] = alloca i32, align 4 +// IR-NEXT: %[[DOTCAPTURE_EXPR_7:.+]] = alloca i32, align 4 +// IR-NEXT: %[[DOTCAPTURE_EXPR_11:.+]] = alloca i32, align 4 +// IR-NEXT: %[[DOTCAPTURE_EXPR_13:.+]] = alloca i32, align 4 // IR-NEXT: %[[DOTFLOOR_0_IV__FLOOR_0_IV_I:.+]] = alloca i32, align 4 // IR-NEXT: %[[DOTOMP_LB:.+]] = alloca i32, align 4 // IR-NEXT: %[[DOTOMP_UB:.+]] = alloca i32, align 4 // IR-NEXT: %[[DOTOMP_STRIDE:.+]] = alloca i32, align 4 // IR-NEXT: %[[DOTOMP_IS_LAST:.+]] = alloca i32, align 4 -// IR-NEXT: %[[DOTFLOOR_0_IV__FLOOR_0_IV_I18:.+]] = alloca i32, align 4 +// IR-NEXT: %[[DOTFLOOR_0_IV__FLOOR_0_IV_I17:.+]] = alloca i32, align 4 // IR-NEXT: %[[DOTTILE_0_IV__FLOOR_0_IV_I:.+]] = alloca i32, align 4 // IR-NEXT: %[[DOTTILE_0_IV_I:.+]] = alloca i32, align 4 -// IR-NEXT: %[[TMP0:.+]] = call i32 @__kmpc_global_thread_num(ptr @2) +// IR-NEXT: %[[TMP0:.+]] = call i32 @__kmpc_global_thread_num(ptr @[[GLOB2:.+]]) // IR-NEXT: store i32 %[[START:.+]], ptr %[[START_ADDR]], align 4 // IR-NEXT: store i32 %[[END:.+]], ptr %[[END_ADDR]], align 4 // IR-NEXT: store i32 %[[STEP:.+]], ptr %[[STEP_ADDR]], align 4 @@ -52,53 +52,53 @@ extern "C" void body(...) {} // IR-NEXT: %[[TMP3:.+]] = load i32, ptr %[[END_ADDR]], align 4 // IR-NEXT: store i32 %[[TMP3]], ptr %[[DOTCAPTURE_EXPR_1]], align 4 // IR-NEXT: %[[TMP4:.+]] = load i32, ptr %[[STEP_ADDR]], align 4 -// IR-NEXT: store i32 %[[TMP4]], ptr %[[DOTCAPTURE_EXPR_2]], align 4 +// IR-NEXT: store i32 %[[TMP4]], ptr %[[DOTNEW_STEP]], align 4 // IR-NEXT: %[[TMP5:.+]] = load i32, ptr %[[DOTCAPTURE_EXPR_1]], align 4 // IR-NEXT: %[[TMP6:.+]] = load i32, ptr %[[DOTCAPTURE_EXPR_]], align 4 // IR-NEXT: %[[SUB:.+]] = sub i32 %[[TMP5]], %[[TMP6]] -// IR-NEXT: %[[SUB4:.+]] = sub i32 %[[SUB]], 1 -// IR-NEXT: %[[TMP7:.+]] = load i32, ptr %[[DOTCAPTURE_EXPR_2]], align 4 -// IR-NEXT: %[[ADD:.+]] = add i32 %[[SUB4]], %[[TMP7]] -// IR-NEXT: %[[TMP8:.+]] = load i32, ptr %[[DOTCAPTURE_EXPR_2]], align 4 +// IR-NEXT: %[[SUB3:.+]] = sub i32 %[[SUB]], 1 +// IR-NEXT: %[[TMP7:.+]] = load i32, ptr %[[DOTNEW_STEP]], align 4 +// IR-NEXT: %[[ADD:.+]] = add i32 %[[SUB3]], %[[TMP7]] +// IR-NEXT: %[[TMP8:.+]] = load i32, ptr %[[DOTNEW_STEP]], align 4 // IR-NEXT: %[[DIV:.+]] = udiv i32 %[[ADD]], %[[TMP8]] -// IR-NEXT: %[[SUB5:.+]] = sub i32 %[[DIV]], 1 -// IR-NEXT: store i32 %[[SUB5]], ptr %[[DOTCAPTURE_EXPR_3]], align 4 +// IR-NEXT: %[[SUB4:.+]] = sub i32 %[[DIV]], 1 +// IR-NEXT: store i32 %[[SUB4]], ptr %[[DOTCAPTURE_EXPR_2]], align 4 // IR-NEXT: store i32 0, ptr %[[DOTFLOOR_0_IV_I]], align 4 -// IR-NEXT: %[[TMP9:.+]] = load i32, ptr %[[DOTCAPTURE_EXPR_3]], align 4 -// IR-NEXT: %[[ADD7:.+]] = add i32 %[[TMP9]], 1 -// IR-NEXT: store i32 %[[ADD7]], ptr %[[DOTCAPTURE_EXPR_6]], align 4 -// IR-NEXT: %[[TMP10:.+]] = load i32, ptr %[[DOTCAPTURE_EXPR_6]], align 4 -// IR-NEXT: %[[SUB9:.+]] = sub i32 %[[TMP10]], -3 -// IR-NEXT: %[[DIV10:.+]] = udiv i32 %[[SUB9]], 4 -// IR-NEXT: %[[SUB11:.+]] = sub i32 %[[DIV10]], 1 -// IR-NEXT: store i32 %[[SUB11]], ptr %[[DOTCAPTURE_EXPR_8]], align 4 -// IR-NEXT: %[[TMP11:.+]] = load i32, ptr %[[DOTCAPTURE_EXPR_8]], align 4 -// IR-NEXT: %[[ADD13:.+]] = add i32 %[[TMP11]], 1 -// IR-NEXT: store i32 %[[ADD13]], ptr %[[DOTCAPTURE_EXPR_12]], align 4 -// IR-NEXT: %[[TMP12:.+]] = load i32, ptr %[[DOTCAPTURE_EXPR_12]], align 4 -// IR-NEXT: %[[SUB15:.+]] = sub i32 %[[TMP12]], -2 -// IR-NEXT: %[[DIV16:.+]] = udiv i32 %[[SUB15]], 3 -// IR-NEXT: %[[SUB17:.+]] = sub i32 %[[DIV16]], 1 -// IR-NEXT: store i32 %[[SUB17]], ptr %[[DOTCAPTURE_EXPR_14]], align 4 +// IR-NEXT: %[[TMP9:.+]] = load i32, ptr %[[DOTCAPTURE_EXPR_2]], align 4 +// IR-NEXT: %[[ADD6:.+]] = add i32 %[[TMP9]], 1 +// IR-NEXT: store i32 %[[ADD6]], ptr %[[DOTCAPTURE_EXPR_5]], align 4 +// IR-NEXT: %[[TMP10:.+]] = load i32, ptr %[[DOTCAPTURE_EXPR_5]], align 4 +// IR-NEXT: %[[SUB8:.+]] = sub i32 %[[TMP10]], -3 +// IR-NEXT: %[[DIV9:.+]] = udiv i32 %[[SUB8]], 4 +// IR-NEXT: %[[SUB10:.+]] = sub i32 %[[DIV9]], 1 +// IR-NEXT: store i32 %[[SUB10]], ptr %[[DOTCAPTURE_EXPR_7]], align 4 +// IR-NEXT: %[[TMP11:.+]] = load i32, ptr %[[DOTCAPTURE_EXPR_7]], align 4 +// IR-NEXT: %[[ADD12:.+]] = add i32 %[[TMP11]], 1 +// IR-NEXT: store i32 %[[ADD12]], ptr %[[DOTCAPTURE_EXPR_11]], align 4 +// IR-NEXT: %[[TMP12:.+]] = load i32, ptr %[[DOTCAPTURE_EXPR_11]], align 4 +// IR-NEXT: %[[SUB14:.+]] = sub i32 %[[TMP12]], -2 +// IR-NEXT: %[[DIV15:.+]] = udiv i32 %[[SUB14]], 3 +// IR-NEXT: %[[SUB16:.+]] = sub i32 %[[DIV15]], 1 +// IR-NEXT: store i32 %[[SUB16]], ptr %[[DOTCAPTURE_EXPR_13]], align 4 // IR-NEXT: store i32 0, ptr %[[DOTFLOOR_0_IV__FLOOR_0_IV_I]], align 4 -// IR-NEXT: %[[TMP13:.+]] = load i32, ptr %[[DOTCAPTURE_EXPR_12]], align 4 +// IR-NEXT: %[[TMP13:.+]] = load i32, ptr %[[DOTCAPTURE_EXPR_11]], align 4 // IR-NEXT: %[[CMP:.+]] = icmp ult i32 0, %[[TMP13]] // IR-NEXT: br i1 %[[CMP]], label %[[OMP_PRECOND_THEN:.+]], label %[[OMP_PRECOND_END:.+]] // IR-EMPTY: // IR-NEXT: [[OMP_PRECOND_THEN]]: // IR-NEXT: store i32 0, ptr %[[DOTOMP_LB]], align 4 -// IR-NEXT: %[[TMP14:.+]] = load i32, ptr %[[DOTCAPTURE_EXPR_14]], align 4 +// IR-NEXT: %[[TMP14:.+]] = load i32, ptr %[[DOTCAPTURE_EXPR_13]], align 4 // IR-NEXT: store i32 %[[TMP14]], ptr %[[DOTOMP_UB]], align 4 // IR-NEXT: store i32 1, ptr %[[DOTOMP_STRIDE]], align 4 // IR-NEXT: store i32 0, ptr %[[DOTOMP_IS_LAST]], align 4 -// IR-NEXT: call void @__kmpc_for_static_init_4u(ptr @1, i32 %[[TMP0]], i32 34, ptr %[[DOTOMP_IS_LAST]], ptr %[[DOTOMP_LB]], ptr %[[DOTOMP_UB]], ptr %[[DOTOMP_STRIDE]], i32 1, i32 1) +// IR-NEXT: call void @__kmpc_for_static_init_4u(ptr @[[GLOB1:.+]], i32 %[[TMP0]], i32 34, ptr %[[DOTOMP_IS_LAST]], ptr %[[DOTOMP_LB]], ptr %[[DOTOMP_UB]], ptr %[[DOTOMP_STRIDE]], i32 1, i32 1) // IR-NEXT: %[[TMP15:.+]] = load i32, ptr %[[DOTOMP_UB]], align 4 -// IR-NEXT: %[[TMP16:.+]] = load i32, ptr %[[DOTCAPTURE_EXPR_14]], align 4 -// IR-NEXT: %[[CMP19:.+]] = icmp ugt i32 %[[TMP15]], %[[TMP16]] -// IR-NEXT: br i1 %[[CMP19]], label %[[COND_TRUE:.+]], label %[[COND_FALSE:.+]] +// IR-NEXT: %[[TMP16:.+]] = load i32, ptr %[[DOTCAPTURE_EXPR_13]], align 4 +// IR-NEXT: %[[CMP18:.+]] = icmp ugt i32 %[[TMP15]], %[[TMP16]] +// IR-NEXT: br i1 %[[CMP18]], label %[[COND_TRUE:.+]], label %[[COND_FALSE:.+]] // IR-EMPTY: // IR-NEXT: [[COND_TRUE]]: -// IR-NEXT: %[[TMP17:.+]] = load i32, ptr %[[DOTCAPTURE_EXPR_14]], align 4 +// IR-NEXT: %[[TMP17:.+]] = load i32, ptr %[[DOTCAPTURE_EXPR_13]], align 4 // IR-NEXT: br label %[[COND_END:.+]] // IR-EMPTY: // IR-NEXT: [[COND_FALSE]]: @@ -115,83 +115,83 @@ extern "C" void body(...) {} // IR-NEXT: [[OMP_INNER_FOR_COND]]: // IR-NEXT: %[[TMP20:.+]] = load i32, ptr %[[DOTOMP_IV]], align 4 // IR-NEXT: %[[TMP21:.+]] = load i32, ptr %[[DOTOMP_UB]], align 4 -// IR-NEXT: %[[ADD20:.+]] = add i32 %[[TMP21]], 1 -// IR-NEXT: %[[CMP21:.+]] = icmp ult i32 %[[TMP20]], %[[ADD20]] -// IR-NEXT: br i1 %[[CMP21]], label %[[OMP_INNER_FOR_BODY:.+]], label %[[OMP_INNER_FOR_END:.+]] +// IR-NEXT: %[[ADD19:.+]] = add i32 %[[TMP21]], 1 +// IR-NEXT: %[[CMP20:.+]] = icmp ult i32 %[[TMP20]], %[[ADD19]] +// IR-NEXT: br i1 %[[CMP20]], label %[[OMP_INNER_FOR_BODY:.+]], label %[[OMP_INNER_FOR_END:.+]] // IR-EMPTY: // IR-NEXT: [[OMP_INNER_FOR_BODY]]: // IR-NEXT: %[[TMP22:.+]] = load i32, ptr %[[DOTOMP_IV]], align 4 // IR-NEXT: %[[MUL:.+]] = mul i32 %[[TMP22]], 3 -// IR-NEXT: %[[ADD22:.+]] = add i32 0, %[[MUL]] -// IR-NEXT: store i32 %[[ADD22]], ptr %[[DOTFLOOR_0_IV__FLOOR_0_IV_I18]], align 4 -// IR-NEXT: %[[TMP23:.+]] = load i32, ptr %[[DOTFLOOR_0_IV__FLOOR_0_IV_I18]], align 4 +// IR-NEXT: %[[ADD21:.+]] = add i32 0, %[[MUL]] +// IR-NEXT: store i32 %[[ADD21]], ptr %[[DOTFLOOR_0_IV__FLOOR_0_IV_I17]], align 4 +// IR-NEXT: %[[TMP23:.+]] = load i32, ptr %[[DOTFLOOR_0_IV__FLOOR_0_IV_I17]], align 4 // IR-NEXT: store i32 %[[TMP23]], ptr %[[DOTTILE_0_IV__FLOOR_0_IV_I]], align 4 // IR-NEXT: br label %[[FOR_COND:.+]] // IR-EMPTY: // IR-NEXT: [[FOR_COND]]: // IR-NEXT: %[[TMP24:.+]] = load i32, ptr %[[DOTTILE_0_IV__FLOOR_0_IV_I]], align 4 -// IR-NEXT: %[[TMP25:.+]] = load i32, ptr %[[DOTCAPTURE_EXPR_8]], align 4 -// IR-NEXT: %[[ADD23:.+]] = add i32 %[[TMP25]], 1 -// IR-NEXT: %[[TMP26:.+]] = load i32, ptr %[[DOTFLOOR_0_IV__FLOOR_0_IV_I18]], align 4 -// IR-NEXT: %[[ADD24:.+]] = add i32 %[[TMP26]], 3 -// IR-NEXT: %[[CMP25:.+]] = icmp ult i32 %[[ADD23]], %[[ADD24]] -// IR-NEXT: br i1 %[[CMP25]], label %[[COND_TRUE26:.+]], label %[[COND_FALSE28:.+]] -// IR-EMPTY: -// IR-NEXT: [[COND_TRUE26]]: -// IR-NEXT: %[[TMP27:.+]] = load i32, ptr %[[DOTCAPTURE_EXPR_8]], align 4 -// IR-NEXT: %[[ADD27:.+]] = add i32 %[[TMP27]], 1 -// IR-NEXT: br label %[[COND_END30:.+]] -// IR-EMPTY: -// IR-NEXT: [[COND_FALSE28]]: -// IR-NEXT: %[[TMP28:.+]] = load i32, ptr %[[DOTFLOOR_0_IV__FLOOR_0_IV_I18]], align 4 -// IR-NEXT: %[[ADD29:.+]] = add i32 %[[TMP28]], 3 -// IR-NEXT: br label %[[COND_END30]] -// IR-EMPTY: -// IR-NEXT: [[COND_END30]]: -// IR-NEXT: %[[COND31:.+]] = phi i32 [ %[[ADD27]], %[[COND_TRUE26]] ], [ %[[ADD29]], %[[COND_FALSE28]] ] -// IR-NEXT: %[[CMP32:.+]] = icmp ult i32 %[[TMP24]], %[[COND31]] -// IR-NEXT: br i1 %[[CMP32]], label %[[FOR_BODY:.+]], label %[[FOR_END51:.+]] +// IR-NEXT: %[[TMP25:.+]] = load i32, ptr %[[DOTCAPTURE_EXPR_7]], align 4 +// IR-NEXT: %[[ADD22:.+]] = add i32 %[[TMP25]], 1 +// IR-NEXT: %[[TMP26:.+]] = load i32, ptr %[[DOTFLOOR_0_IV__FLOOR_0_IV_I17]], align 4 +// IR-NEXT: %[[ADD23:.+]] = add i32 %[[TMP26]], 3 +// IR-NEXT: %[[CMP24:.+]] = icmp ult i32 %[[ADD22]], %[[ADD23]] +// IR-NEXT: br i1 %[[CMP24]], label %[[COND_TRUE25:.+]], label %[[COND_FALSE27:.+]] +// IR-EMPTY: +// IR-NEXT: [[COND_TRUE25]]: +// IR-NEXT: %[[TMP27:.+]] = load i32, ptr %[[DOTCAPTURE_EXPR_7]], align 4 +// IR-NEXT: %[[ADD26:.+]] = add i32 %[[TMP27]], 1 +// IR-NEXT: br label %[[COND_END29:.+]] +// IR-EMPTY: +// IR-NEXT: [[COND_FALSE27]]: +// IR-NEXT: %[[TMP28:.+]] = load i32, ptr %[[DOTFLOOR_0_IV__FLOOR_0_IV_I17]], align 4 +// IR-NEXT: %[[ADD28:.+]] = add i32 %[[TMP28]], 3 +// IR-NEXT: br label %[[COND_END29]] +// IR-EMPTY: +// IR-NEXT: [[COND_END29]]: +// IR-NEXT: %[[COND30:.+]] = phi i32 [ %[[ADD26]], %[[COND_TRUE25]] ], [ %[[ADD28]], %[[COND_FALSE27]] ] +// IR-NEXT: %[[CMP31:.+]] = icmp ult i32 %[[TMP24]], %[[COND30]] +// IR-NEXT: br i1 %[[CMP31]], label %[[FOR_BODY:.+]], label %[[FOR_END50:.+]] // IR-EMPTY: // IR-NEXT: [[FOR_BODY]]: // IR-NEXT: %[[TMP29:.+]] = load i32, ptr %[[DOTTILE_0_IV__FLOOR_0_IV_I]], align 4 -// IR-NEXT: %[[MUL33:.+]] = mul i32 %[[TMP29]], 4 -// IR-NEXT: %[[ADD34:.+]] = add i32 0, %[[MUL33]] -// IR-NEXT: store i32 %[[ADD34]], ptr %[[DOTFLOOR_0_IV_I]], align 4 +// IR-NEXT: %[[MUL32:.+]] = mul i32 %[[TMP29]], 4 +// IR-NEXT: %[[ADD33:.+]] = add i32 0, %[[MUL32]] +// IR-NEXT: store i32 %[[ADD33]], ptr %[[DOTFLOOR_0_IV_I]], align 4 // IR-NEXT: %[[TMP30:.+]] = load i32, ptr %[[DOTFLOOR_0_IV_I]], align 4 // IR-NEXT: store i32 %[[TMP30]], ptr %[[DOTTILE_0_IV_I]], align 4 -// IR-NEXT: br label %[[FOR_COND35:.+]] +// IR-NEXT: br label %[[FOR_COND34:.+]] // IR-EMPTY: -// IR-NEXT: [[FOR_COND35]]: +// IR-NEXT: [[FOR_COND34]]: // IR-NEXT: %[[TMP31:.+]] = load i32, ptr %[[DOTTILE_0_IV_I]], align 4 -// IR-NEXT: %[[TMP32:.+]] = load i32, ptr %[[DOTCAPTURE_EXPR_3]], align 4 -// IR-NEXT: %[[ADD36:.+]] = add i32 %[[TMP32]], 1 +// IR-NEXT: %[[TMP32:.+]] = load i32, ptr %[[DOTCAPTURE_EXPR_2]], align 4 +// IR-NEXT: %[[ADD35:.+]] = add i32 %[[TMP32]], 1 // IR-NEXT: %[[TMP33:.+]] = load i32, ptr %[[DOTFLOOR_0_IV_I]], align 4 -// IR-NEXT: %[[ADD37:.+]] = add nsw i32 %[[TMP33]], 4 -// IR-NEXT: %[[CMP38:.+]] = icmp ult i32 %[[ADD36]], %[[ADD37]] -// IR-NEXT: br i1 %[[CMP38]], label %[[COND_TRUE39:.+]], label %[[COND_FALSE41:.+]] +// IR-NEXT: %[[ADD36:.+]] = add i32 %[[TMP33]], 4 +// IR-NEXT: %[[CMP37:.+]] = icmp ult i32 %[[ADD35]], %[[ADD36]] +// IR-NEXT: br i1 %[[CMP37]], label %[[COND_TRUE38:.+]], label %[[COND_FALSE40:.+]] // IR-EMPTY: -// IR-NEXT: [[COND_TRUE39]]: -// IR-NEXT: %[[TMP34:.+]] = load i32, ptr %[[DOTCAPTURE_EXPR_3]], align 4 -// IR-NEXT: %[[ADD40:.+]] = add i32 %[[TMP34]], 1 -// IR-NEXT: br label %[[COND_END43:.+]] +// IR-NEXT: [[COND_TRUE38]]: +// IR-NEXT: %[[TMP34:.+]] = load i32, ptr %[[DOTCAPTURE_EXPR_2]], align 4 +// IR-NEXT: %[[ADD39:.+]] = add i32 %[[TMP34]], 1 +// IR-NEXT: br label %[[COND_END42:.+]] // IR-EMPTY: -// IR-NEXT: [[COND_FALSE41]]: +// IR-NEXT: [[COND_FALSE40]]: // IR-NEXT: %[[TMP35:.+]] = load i32, ptr %[[DOTFLOOR_0_IV_I]], align 4 -// IR-NEXT: %[[ADD42:.+]] = add nsw i32 %[[TMP35]], 4 -// IR-NEXT: br label %[[COND_END43]] +// IR-NEXT: %[[ADD41:.+]] = add i32 %[[TMP35]], 4 +// IR-NEXT: br label %[[COND_END42]] // IR-EMPTY: -// IR-NEXT: [[COND_END43]]: -// IR-NEXT: %[[COND44:.+]] = phi i32 [ %[[ADD40]], %[[COND_TRUE39]] ], [ %[[ADD42]], %[[COND_FALSE41]] ] -// IR-NEXT: %[[CMP45:.+]] = icmp ult i32 %[[TMP31]], %[[COND44]] -// IR-NEXT: br i1 %[[CMP45]], label %[[FOR_BODY46:.+]], label %[[FOR_END:.+]] +// IR-NEXT: [[COND_END42]]: +// IR-NEXT: %[[COND43:.+]] = phi i32 [ %[[ADD39]], %[[COND_TRUE38]] ], [ %[[ADD41]], %[[COND_FALSE40]] ] +// IR-NEXT: %[[CMP44:.+]] = icmp ult i32 %[[TMP31]], %[[COND43]] +// IR-NEXT: br i1 %[[CMP44]], label %[[FOR_BODY45:.+]], label %[[FOR_END:.+]] // IR-EMPTY: -// IR-NEXT: [[FOR_BODY46]]: +// IR-NEXT: [[FOR_BODY45]]: // IR-NEXT: %[[TMP36:.+]] = load i32, ptr %[[DOTCAPTURE_EXPR_]], align 4 // IR-NEXT: %[[TMP37:.+]] = load i32, ptr %[[DOTTILE_0_IV_I]], align 4 -// IR-NEXT: %[[TMP38:.+]] = load i32, ptr %[[DOTCAPTURE_EXPR_2]], align 4 -// IR-NEXT: %[[MUL47:.+]] = mul i32 %[[TMP37]], %[[TMP38]] -// IR-NEXT: %[[ADD48:.+]] = add i32 %[[TMP36]], %[[MUL47]] -// IR-NEXT: store i32 %[[ADD48]], ptr %[[I]], align 4 +// IR-NEXT: %[[TMP38:.+]] = load i32, ptr %[[DOTNEW_STEP]], align 4 +// IR-NEXT: %[[MUL46:.+]] = mul i32 %[[TMP37]], %[[TMP38]] +// IR-NEXT: %[[ADD47:.+]] = add i32 %[[TMP36]], %[[MUL46]] +// IR-NEXT: store i32 %[[ADD47]], ptr %[[I]], align 4 // IR-NEXT: %[[TMP39:.+]] = load i32, ptr %[[START_ADDR]], align 4 // IR-NEXT: %[[TMP40:.+]] = load i32, ptr %[[END_ADDR]], align 4 // IR-NEXT: %[[TMP41:.+]] = load i32, ptr %[[STEP_ADDR]], align 4 @@ -201,20 +201,20 @@ extern "C" void body(...) {} // IR-EMPTY: // IR-NEXT: [[FOR_INC]]: // IR-NEXT: %[[TMP43:.+]] = load i32, ptr %[[DOTTILE_0_IV_I]], align 4 -// IR-NEXT: %[[INC:.+]] = add nsw i32 %[[TMP43]], 1 +// IR-NEXT: %[[INC:.+]] = add i32 %[[TMP43]], 1 // IR-NEXT: store i32 %[[INC]], ptr %[[DOTTILE_0_IV_I]], align 4 -// IR-NEXT: br label %[[FOR_COND35]], !llvm.loop ![[LOOP2:[0-9]+]] +// IR-NEXT: br label %[[FOR_COND34]], !llvm.loop ![[LOOP3:[0-9]+]] // IR-EMPTY: // IR-NEXT: [[FOR_END]]: -// IR-NEXT: br label %[[FOR_INC49:.+]] +// IR-NEXT: br label %[[FOR_INC48:.+]] // IR-EMPTY: -// IR-NEXT: [[FOR_INC49]]: +// IR-NEXT: [[FOR_INC48]]: // IR-NEXT: %[[TMP44:.+]] = load i32, ptr %[[DOTTILE_0_IV__FLOOR_0_IV_I]], align 4 -// IR-NEXT: %[[INC50:.+]] = add i32 %[[TMP44]], 1 -// IR-NEXT: store i32 %[[INC50]], ptr %[[DOTTILE_0_IV__FLOOR_0_IV_I]], align 4 -// IR-NEXT: br label %[[FOR_COND]], !llvm.loop ![[LOOP4:[0-9]+]] +// IR-NEXT: %[[INC49:.+]] = add i32 %[[TMP44]], 1 +// IR-NEXT: store i32 %[[INC49]], ptr %[[DOTTILE_0_IV__FLOOR_0_IV_I]], align 4 +// IR-NEXT: br label %[[FOR_COND]], !llvm.loop ![[LOOP5:[0-9]+]] // IR-EMPTY: -// IR-NEXT: [[FOR_END51]]: +// IR-NEXT: [[FOR_END50]]: // IR-NEXT: br label %[[OMP_BODY_CONTINUE:.+]] // IR-EMPTY: // IR-NEXT: [[OMP_BODY_CONTINUE]]: @@ -222,21 +222,23 @@ extern "C" void body(...) {} // IR-EMPTY: // IR-NEXT: [[OMP_INNER_FOR_INC]]: // IR-NEXT: %[[TMP45:.+]] = load i32, ptr %[[DOTOMP_IV]], align 4 -// IR-NEXT: %[[ADD52:.+]] = add i32 %[[TMP45]], 1 -// IR-NEXT: store i32 %[[ADD52]], ptr %[[DOTOMP_IV]], align 4 +// IR-NEXT: %[[ADD51:.+]] = add i32 %[[TMP45]], 1 +// IR-NEXT: store i32 %[[ADD51]], ptr %[[DOTOMP_IV]], align 4 // IR-NEXT: br label %[[OMP_INNER_FOR_COND]] // IR-EMPTY: // IR-NEXT: [[OMP_INNER_FOR_END]]: // IR-NEXT: br label %[[OMP_LOOP_EXIT:.+]] // IR-EMPTY: // IR-NEXT: [[OMP_LOOP_EXIT]]: -// IR-NEXT: call void @__kmpc_for_static_fini(ptr @1, i32 %[[TMP0]]) +// IR-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 %[[TMP0]]) // IR-NEXT: br label %[[OMP_PRECOND_END]] // IR-EMPTY: // IR-NEXT: [[OMP_PRECOND_END]]: -// IR-NEXT: call void @__kmpc_barrier(ptr @3, i32 %[[TMP0]]) +// IR-NEXT: call void @__kmpc_barrier(ptr @[[GLOB3:.+]], i32 %[[TMP0]]) // IR-NEXT: ret void // IR-NEXT: } + + extern "C" void func(int start, int end, int step) { #pragma omp for #pragma omp tile sizes(3) @@ -246,8 +248,10 @@ extern "C" void func(int start, int end, int step) { } #endif /* HEADER */ + // IR: ![[META0:[0-9]+]] = !{i32 1, !"wchar_size", i32 4} -// IR: ![[META1:[0-9]+]] = !{!"{{[^"]*}}"} -// IR: ![[LOOP2]] = distinct !{![[LOOP2]], ![[LOOPPROP3:[0-9]+]]} -// IR: ![[LOOPPROP3]] = !{!"llvm.loop.mustprogress"} -// IR: ![[LOOP4]] = distinct !{![[LOOP4]], ![[LOOPPROP3]]} +// IR: ![[META1:[0-9]+]] = !{i32 7, !"openmp", i32 51} +// IR: ![[META2:[0-9]+]] = +// IR: ![[LOOP3]] = distinct !{![[LOOP3]], ![[LOOPPROP4:[0-9]+]]} +// IR: ![[LOOPPROP4]] = !{!"llvm.loop.mustprogress"} +// IR: ![[LOOP5]] = distinct !{![[LOOP5]], ![[LOOPPROP4]]} diff --git a/openmp/runtime/test/lit.cfg b/openmp/runtime/test/lit.cfg index e8f7f3470580..14c746898213 100644 --- a/openmp/runtime/test/lit.cfg +++ b/openmp/runtime/test/lit.cfg @@ -171,10 +171,14 @@ config.substitutions.append(("%libomp-c99-compile-and-run", \ "%libomp-c99-compile && %libomp-run")) config.substitutions.append(("%libomp-cxx-compile-and-run", \ "%libomp-cxx-compile && %libomp-run")) +config.substitutions.append(("%libomp-cxx20-compile-and-run", \ + "%libomp-cxx20-compile && %libomp-run")) config.substitutions.append(("%libomp-cxx-compile-c", \ "%clangXX %openmp_flags %flags -std=c++17 -x c++ %s -o %t" + libs)) config.substitutions.append(("%libomp-cxx-compile", \ "%clangXX %openmp_flags %flags -std=c++17 %s -o %t" + libs)) +config.substitutions.append(("%libomp-cxx20-compile", \ + "%clangXX %openmp_flags %flags -std=c++20 %s -o %t" + libs)) config.substitutions.append(("%libomp-compile", \ "%clang %openmp_flags %flags %s -o %t" + libs)) config.substitutions.append(("%libomp-irbuilder-compile", \ diff --git a/openmp/runtime/test/transform/tile/foreach.cpp b/openmp/runtime/test/transform/tile/foreach.cpp new file mode 100644 index 000000000000..4fb359576097 --- /dev/null +++ b/openmp/runtime/test/transform/tile/foreach.cpp @@ -0,0 +1,228 @@ +// RUN: %libomp-cxx20-compile-and-run | FileCheck %s --match-full-lines + +#ifndef HEADER +#define HEADER + +#include +#include +#include +#include + +struct Reporter { + const char *name; + + Reporter(const char *name) : name(name) { print("ctor"); } + + Reporter() : name("") { print("ctor"); } + + Reporter(const Reporter &that) : name(that.name) { print("copy ctor"); } + + Reporter(Reporter &&that) : name(that.name) { print("move ctor"); } + + ~Reporter() { print("dtor"); } + + const Reporter &operator=(const Reporter &that) { + print("copy assign"); + this->name = that.name; + return *this; + } + + const Reporter &operator=(Reporter &&that) { + print("move assign"); + this->name = that.name; + return *this; + } + + struct Iterator { + const Reporter *owner; + int pos; + + Iterator(const Reporter *owner, int pos) : owner(owner), pos(pos) {} + + Iterator(const Iterator &that) : owner(that.owner), pos(that.pos) { + owner->print("iterator copy ctor"); + } + + Iterator(Iterator &&that) : owner(that.owner), pos(that.pos) { + owner->print("iterator move ctor"); + } + + ~Iterator() { owner->print("iterator dtor"); } + + const Iterator &operator=(const Iterator &that) { + owner->print("iterator copy assign"); + this->owner = that.owner; + this->pos = that.pos; + return *this; + } + + const Iterator &operator=(Iterator &&that) { + owner->print("iterator move assign"); + this->owner = that.owner; + this->pos = that.pos; + return *this; + } + + bool operator==(const Iterator &that) const { + owner->print("iterator %d == %d", 2 - this->pos, 2 - that.pos); + return this->pos == that.pos; + } + + Iterator &operator++() { + owner->print("iterator prefix ++"); + pos -= 1; + return *this; + } + + Iterator operator++(int) { + owner->print("iterator postfix ++"); + auto result = *this; + pos -= 1; + return result; + } + + int operator*() const { + int result = 2 - pos; + owner->print("iterator deref: %i", result); + return result; + } + + size_t operator-(const Iterator &that) const { + int result = (2 - this->pos) - (2 - that.pos); + owner->print("iterator distance: %d", result); + return result; + } + + Iterator operator+(int steps) const { + owner->print("iterator advance: %i += %i", 2 - this->pos, steps); + return Iterator(owner, pos - steps); + } + + void print(const char *msg) const { owner->print(msg); } + }; + + Iterator begin() const { + print("begin()"); + return Iterator(this, 2); + } + + Iterator end() const { + print("end()"); + return Iterator(this, -1); + } + + void print(const char *msg, ...) const { + va_list args; + va_start(args, msg); + printf("[%s] ", name); + vprintf(msg, args); + printf("\n"); + va_end(args); + } +}; + +int main() { + printf("do\n"); +#pragma omp tile sizes(2, 2) + for (Reporter c{"C"}; auto &&v : Reporter("A")) + for (Reporter d{"D"}; auto &&w : Reporter("B")) + printf("v=%d w=%d\n", v, w); + printf("done\n"); + return EXIT_SUCCESS; +} + +#endif /* HEADER */ + +// CHECK: do +// CHECK-NEXT: [C] ctor +// CHECK-NEXT: [A] ctor +// CHECK-NEXT: [A] end() +// CHECK-NEXT: [A] begin() +// CHECK-NEXT: [A] begin() +// CHECK-NEXT: [A] iterator distance: 3 +// CHECK-NEXT: [D] ctor +// CHECK-NEXT: [B] ctor +// CHECK-NEXT: [B] end() +// CHECK-NEXT: [B] begin() +// CHECK-NEXT: [B] begin() +// CHECK-NEXT: [B] iterator distance: 3 +// CHECK-NEXT: [A] iterator advance: 0 += 0 +// CHECK-NEXT: [A] iterator move assign +// CHECK-NEXT: [A] iterator deref: 0 +// CHECK-NEXT: [B] iterator advance: 0 += 0 +// CHECK-NEXT: [B] iterator move assign +// CHECK-NEXT: [B] iterator deref: 0 +// CHECK-NEXT: v=0 w=0 +// CHECK-NEXT: [B] iterator dtor +// CHECK-NEXT: [B] iterator advance: 0 += 1 +// CHECK-NEXT: [B] iterator move assign +// CHECK-NEXT: [B] iterator deref: 1 +// CHECK-NEXT: v=0 w=1 +// CHECK-NEXT: [B] iterator dtor +// CHECK-NEXT: [A] iterator dtor +// CHECK-NEXT: [A] iterator advance: 0 += 1 +// CHECK-NEXT: [A] iterator move assign +// CHECK-NEXT: [A] iterator deref: 1 +// CHECK-NEXT: [B] iterator advance: 0 += 0 +// CHECK-NEXT: [B] iterator move assign +// CHECK-NEXT: [B] iterator deref: 0 +// CHECK-NEXT: v=1 w=0 +// CHECK-NEXT: [B] iterator dtor +// CHECK-NEXT: [B] iterator advance: 0 += 1 +// CHECK-NEXT: [B] iterator move assign +// CHECK-NEXT: [B] iterator deref: 1 +// CHECK-NEXT: v=1 w=1 +// CHECK-NEXT: [B] iterator dtor +// CHECK-NEXT: [A] iterator dtor +// CHECK-NEXT: [A] iterator advance: 0 += 0 +// CHECK-NEXT: [A] iterator move assign +// CHECK-NEXT: [A] iterator deref: 0 +// CHECK-NEXT: [B] iterator advance: 0 += 2 +// CHECK-NEXT: [B] iterator move assign +// CHECK-NEXT: [B] iterator deref: 2 +// CHECK-NEXT: v=0 w=2 +// CHECK-NEXT: [B] iterator dtor +// CHECK-NEXT: [A] iterator dtor +// CHECK-NEXT: [A] iterator advance: 0 += 1 +// CHECK-NEXT: [A] iterator move assign +// CHECK-NEXT: [A] iterator deref: 1 +// CHECK-NEXT: [B] iterator advance: 0 += 2 +// CHECK-NEXT: [B] iterator move assign +// CHECK-NEXT: [B] iterator deref: 2 +// CHECK-NEXT: v=1 w=2 +// CHECK-NEXT: [B] iterator dtor +// CHECK-NEXT: [A] iterator dtor +// CHECK-NEXT: [A] iterator advance: 0 += 2 +// CHECK-NEXT: [A] iterator move assign +// CHECK-NEXT: [A] iterator deref: 2 +// CHECK-NEXT: [B] iterator advance: 0 += 0 +// CHECK-NEXT: [B] iterator move assign +// CHECK-NEXT: [B] iterator deref: 0 +// CHECK-NEXT: v=2 w=0 +// CHECK-NEXT: [B] iterator dtor +// CHECK-NEXT: [B] iterator advance: 0 += 1 +// CHECK-NEXT: [B] iterator move assign +// CHECK-NEXT: [B] iterator deref: 1 +// CHECK-NEXT: v=2 w=1 +// CHECK-NEXT: [B] iterator dtor +// CHECK-NEXT: [A] iterator dtor +// CHECK-NEXT: [A] iterator advance: 0 += 2 +// CHECK-NEXT: [A] iterator move assign +// CHECK-NEXT: [A] iterator deref: 2 +// CHECK-NEXT: [B] iterator advance: 0 += 2 +// CHECK-NEXT: [B] iterator move assign +// CHECK-NEXT: [B] iterator deref: 2 +// CHECK-NEXT: v=2 w=2 +// CHECK-NEXT: [B] iterator dtor +// CHECK-NEXT: [A] iterator dtor +// CHECK-NEXT: [B] iterator dtor +// CHECK-NEXT: [B] iterator dtor +// CHECK-NEXT: [B] iterator dtor +// CHECK-NEXT: [B] dtor +// CHECK-NEXT: [D] dtor +// CHECK-NEXT: [A] iterator dtor +// CHECK-NEXT: [A] iterator dtor +// CHECK-NEXT: [A] iterator dtor +// CHECK-NEXT: [A] dtor +// CHECK-NEXT: [C] dtor +// CHECK-NEXT: done diff --git a/openmp/runtime/test/transform/tile/iterfor.cpp b/openmp/runtime/test/transform/tile/iterfor.cpp new file mode 100644 index 000000000000..12613544f6e5 --- /dev/null +++ b/openmp/runtime/test/transform/tile/iterfor.cpp @@ -0,0 +1,233 @@ +// RUN: %libomp-cxx20-compile-and-run | FileCheck %s --match-full-lines + +#ifndef HEADER +#define HEADER + +#include +#include +#include +#include + +struct Reporter { + const char *name; + + Reporter(const char *name) : name(name) { print("ctor"); } + + Reporter() : name("") { print("ctor"); } + + Reporter(const Reporter &that) : name(that.name) { print("copy ctor"); } + + Reporter(Reporter &&that) : name(that.name) { print("move ctor"); } + + ~Reporter() { print("dtor"); } + + const Reporter &operator=(const Reporter &that) { + print("copy assign"); + this->name = that.name; + return *this; + } + + const Reporter &operator=(Reporter &&that) { + print("move assign"); + this->name = that.name; + return *this; + } + + struct Iterator { + const Reporter *owner; + int pos; + + Iterator(const Reporter *owner, int pos) : owner(owner), pos(pos) {} + + Iterator(const Iterator &that) : owner(that.owner), pos(that.pos) { + owner->print("iterator copy ctor"); + } + + Iterator(Iterator &&that) : owner(that.owner), pos(that.pos) { + owner->print("iterator move ctor"); + } + + ~Iterator() { owner->print("iterator dtor"); } + + const Iterator &operator=(const Iterator &that) { + owner->print("iterator copy assign"); + this->owner = that.owner; + this->pos = that.pos; + return *this; + } + + const Iterator &operator=(Iterator &&that) { + owner->print("iterator move assign"); + this->owner = that.owner; + this->pos = that.pos; + return *this; + } + + bool operator==(const Iterator &that) const { + owner->print("iterator %d == %d", 2 - this->pos, 2 - that.pos); + return this->pos == that.pos; + } + + bool operator!=(const Iterator &that) const { + owner->print("iterator %d != %d", 2 - this->pos, 2 - that.pos); + return this->pos == that.pos; + } + + Iterator &operator++() { + owner->print("iterator prefix ++"); + pos -= 1; + return *this; + } + + Iterator operator++(int) { + owner->print("iterator postfix ++"); + auto result = *this; + pos -= 1; + return result; + } + + int operator*() const { + int result = 2 - pos; + owner->print("iterator deref: %i", result); + return result; + } + + size_t operator-(const Iterator &that) const { + int result = (2 - this->pos) - (2 - that.pos); + owner->print("iterator distance: %d", result); + return result; + } + + Iterator operator+(int steps) const { + owner->print("iterator advance: %i += %i", 2 - this->pos, steps); + return Iterator(owner, pos - steps); + } + }; + + Iterator begin() const { + print("begin()"); + return Iterator(this, 2); + } + + Iterator end() const { + print("end()"); + return Iterator(this, -1); + } + + void print(const char *msg, ...) const { + va_list args; + va_start(args, msg); + printf("[%s] ", name); + vprintf(msg, args); + printf("\n"); + va_end(args); + } +}; + +int main() { + printf("do\n"); + { + Reporter A("A"), B("B"); +#pragma omp tile sizes(2, 2) + for (auto it = A.begin(); it != A.end(); ++it) + for (auto jt = B.begin(); jt != B.end(); ++jt) + printf("i=%d j=%d\n", *it, *jt); + } + printf("done\n"); + return EXIT_SUCCESS; +} + +#endif /* HEADER */ + +// CHECK: do +// CHECK-NEXT: [A] ctor +// CHECK-NEXT: [B] ctor +// CHECK-NEXT: [A] begin() +// CHECK-NEXT: [A] begin() +// CHECK-NEXT: [A] end() +// CHECK-NEXT: [A] iterator distance: 3 +// CHECK-NEXT: [B] begin() +// CHECK-NEXT: [B] begin() +// CHECK-NEXT: [B] end() +// CHECK-NEXT: [B] iterator distance: 3 +// CHECK-NEXT: [A] iterator advance: 0 += 0 +// CHECK-NEXT: [A] iterator move assign +// CHECK-NEXT: [B] iterator advance: 0 += 0 +// CHECK-NEXT: [B] iterator move assign +// CHECK-NEXT: [A] iterator deref: 0 +// CHECK-NEXT: [B] iterator deref: 0 +// CHECK-NEXT: i=0 j=0 +// CHECK-NEXT: [B] iterator dtor +// CHECK-NEXT: [B] iterator advance: 0 += 1 +// CHECK-NEXT: [B] iterator move assign +// CHECK-NEXT: [A] iterator deref: 0 +// CHECK-NEXT: [B] iterator deref: 1 +// CHECK-NEXT: i=0 j=1 +// CHECK-NEXT: [B] iterator dtor +// CHECK-NEXT: [A] iterator dtor +// CHECK-NEXT: [A] iterator advance: 0 += 1 +// CHECK-NEXT: [A] iterator move assign +// CHECK-NEXT: [B] iterator advance: 0 += 0 +// CHECK-NEXT: [B] iterator move assign +// CHECK-NEXT: [A] iterator deref: 1 +// CHECK-NEXT: [B] iterator deref: 0 +// CHECK-NEXT: i=1 j=0 +// CHECK-NEXT: [B] iterator dtor +// CHECK-NEXT: [B] iterator advance: 0 += 1 +// CHECK-NEXT: [B] iterator move assign +// CHECK-NEXT: [A] iterator deref: 1 +// CHECK-NEXT: [B] iterator deref: 1 +// CHECK-NEXT: i=1 j=1 +// CHECK-NEXT: [B] iterator dtor +// CHECK-NEXT: [A] iterator dtor +// CHECK-NEXT: [A] iterator advance: 0 += 0 +// CHECK-NEXT: [A] iterator move assign +// CHECK-NEXT: [B] iterator advance: 0 += 2 +// CHECK-NEXT: [B] iterator move assign +// CHECK-NEXT: [A] iterator deref: 0 +// CHECK-NEXT: [B] iterator deref: 2 +// CHECK-NEXT: i=0 j=2 +// CHECK-NEXT: [B] iterator dtor +// CHECK-NEXT: [A] iterator dtor +// CHECK-NEXT: [A] iterator advance: 0 += 1 +// CHECK-NEXT: [A] iterator move assign +// CHECK-NEXT: [B] iterator advance: 0 += 2 +// CHECK-NEXT: [B] iterator move assign +// CHECK-NEXT: [A] iterator deref: 1 +// CHECK-NEXT: [B] iterator deref: 2 +// CHECK-NEXT: i=1 j=2 +// CHECK-NEXT: [B] iterator dtor +// CHECK-NEXT: [A] iterator dtor +// CHECK-NEXT: [A] iterator advance: 0 += 2 +// CHECK-NEXT: [A] iterator move assign +// CHECK-NEXT: [B] iterator advance: 0 += 0 +// CHECK-NEXT: [B] iterator move assign +// CHECK-NEXT: [A] iterator deref: 2 +// CHECK-NEXT: [B] iterator deref: 0 +// CHECK-NEXT: i=2 j=0 +// CHECK-NEXT: [B] iterator dtor +// CHECK-NEXT: [B] iterator advance: 0 += 1 +// CHECK-NEXT: [B] iterator move assign +// CHECK-NEXT: [A] iterator deref: 2 +// CHECK-NEXT: [B] iterator deref: 1 +// CHECK-NEXT: i=2 j=1 +// CHECK-NEXT: [B] iterator dtor +// CHECK-NEXT: [A] iterator dtor +// CHECK-NEXT: [A] iterator advance: 0 += 2 +// CHECK-NEXT: [A] iterator move assign +// CHECK-NEXT: [B] iterator advance: 0 += 2 +// CHECK-NEXT: [B] iterator move assign +// CHECK-NEXT: [A] iterator deref: 2 +// CHECK-NEXT: [B] iterator deref: 2 +// CHECK-NEXT: i=2 j=2 +// CHECK-NEXT: [B] iterator dtor +// CHECK-NEXT: [A] iterator dtor +// CHECK-NEXT: [B] iterator dtor +// CHECK-NEXT: [B] iterator dtor +// CHECK-NEXT: [A] iterator dtor +// CHECK-NEXT: [A] iterator dtor +// CHECK-NEXT: [B] iterator dtor +// CHECK-NEXT: [A] iterator dtor +// CHECK-NEXT: [B] dtor +// CHECK-NEXT: [A] dtor +// CHECK-NEXT: done diff --git a/openmp/runtime/test/transform/tile/parallel-wsloop-collapse-foreach.cpp b/openmp/runtime/test/transform/tile/parallel-wsloop-collapse-foreach.cpp new file mode 100644 index 000000000000..b1f4d98a52dd --- /dev/null +++ b/openmp/runtime/test/transform/tile/parallel-wsloop-collapse-foreach.cpp @@ -0,0 +1,366 @@ +// RUN: %libomp-cxx20-compile-and-run | FileCheck %s --match-full-lines + +#ifndef HEADER +#define HEADER + +#include +#include +#include +#include + +struct Reporter { + const char *name; + + Reporter(const char *name) : name(name) { print("ctor"); } + + Reporter() : name("") { print("ctor"); } + + Reporter(const Reporter &that) : name(that.name) { print("copy ctor"); } + + Reporter(Reporter &&that) : name(that.name) { print("move ctor"); } + + ~Reporter() { print("dtor"); } + + const Reporter &operator=(const Reporter &that) { + print("copy assign"); + this->name = that.name; + return *this; + } + + const Reporter &operator=(Reporter &&that) { + print("move assign"); + this->name = that.name; + return *this; + } + + struct Iterator { + const Reporter *owner; + int pos; + + Iterator(const Reporter *owner, int pos) : owner(owner), pos(pos) {} + + Iterator(const Iterator &that) : owner(that.owner), pos(that.pos) { + owner->print("iterator copy ctor"); + } + + Iterator(Iterator &&that) : owner(that.owner), pos(that.pos) { + owner->print("iterator move ctor"); + } + + ~Iterator() { owner->print("iterator dtor"); } + + const Iterator &operator=(const Iterator &that) { + owner->print("iterator copy assign"); + this->owner = that.owner; + this->pos = that.pos; + return *this; + } + + const Iterator &operator=(Iterator &&that) { + owner->print("iterator move assign"); + this->owner = that.owner; + this->pos = that.pos; + return *this; + } + + bool operator==(const Iterator &that) const { + owner->print("iterator %d == %d", 2 - this->pos, 2 - that.pos); + return this->pos == that.pos; + } + + Iterator &operator++() { + owner->print("iterator prefix ++"); + pos -= 1; + return *this; + } + + Iterator operator++(int) { + owner->print("iterator postfix ++"); + auto result = *this; + pos -= 1; + return result; + } + + int operator*() const { + int result = 2 - pos; + owner->print("iterator deref: %i", result); + return result; + } + + size_t operator-(const Iterator &that) const { + int result = (2 - this->pos) - (2 - that.pos); + owner->print("iterator distance: %d", result); + return result; + } + + Iterator operator+(int steps) const { + owner->print("iterator advance: %i += %i", 2 - this->pos, steps); + return Iterator(owner, pos - steps); + } + }; + + Iterator begin() const { + print("begin()"); + return Iterator(this, 2); + } + + Iterator end() const { + print("end()"); + return Iterator(this, -1); + } + + void print(const char *msg, ...) const { + va_list args; + va_start(args, msg); + printf("[%s] ", name); + vprintf(msg, args); + printf("\n"); + va_end(args); + } +}; + +int main() { + printf("do\n"); +#pragma omp parallel for collapse(3) num_threads(1) + for (int i = 0; i < 3; ++i) +#pragma omp tile sizes(2, 2) + for (Reporter c{"C"}; auto &&v : Reporter("A")) + for (Reporter d{"D"}; auto &&w : Reporter("B")) + printf("i=%d v=%d w=%d\n", i, v, w); + printf("done\n"); + return EXIT_SUCCESS; +} + +#endif /* HEADER */ + +// CHECK: do +// CHECK-NEXT: [C] ctor +// CHECK-NEXT: [A] ctor +// CHECK-NEXT: [A] end() +// CHECK-NEXT: [A] begin() +// CHECK-NEXT: [A] begin() +// CHECK-NEXT: [A] iterator distance: 3 +// CHECK-NEXT: [D] ctor +// CHECK-NEXT: [B] ctor +// CHECK-NEXT: [B] end() +// CHECK-NEXT: [B] begin() +// CHECK-NEXT: [B] begin() +// CHECK-NEXT: [B] iterator distance: 3 +// CHECK-NEXT: [A] iterator advance: 0 += 0 +// CHECK-NEXT: [A] iterator move assign +// CHECK-NEXT: [A] iterator deref: 0 +// CHECK-NEXT: [B] iterator advance: 0 += 0 +// CHECK-NEXT: [B] iterator move assign +// CHECK-NEXT: [B] iterator deref: 0 +// CHECK-NEXT: i=0 v=0 w=0 +// CHECK-NEXT: [B] iterator dtor +// CHECK-NEXT: [B] iterator advance: 0 += 1 +// CHECK-NEXT: [B] iterator move assign +// CHECK-NEXT: [B] iterator deref: 1 +// CHECK-NEXT: i=0 v=0 w=1 +// CHECK-NEXT: [B] iterator dtor +// CHECK-NEXT: [A] iterator dtor +// CHECK-NEXT: [A] iterator advance: 0 += 1 +// CHECK-NEXT: [A] iterator move assign +// CHECK-NEXT: [A] iterator deref: 1 +// CHECK-NEXT: [B] iterator advance: 0 += 0 +// CHECK-NEXT: [B] iterator move assign +// CHECK-NEXT: [B] iterator deref: 0 +// CHECK-NEXT: i=0 v=1 w=0 +// CHECK-NEXT: [B] iterator dtor +// CHECK-NEXT: [B] iterator advance: 0 += 1 +// CHECK-NEXT: [B] iterator move assign +// CHECK-NEXT: [B] iterator deref: 1 +// CHECK-NEXT: i=0 v=1 w=1 +// CHECK-NEXT: [B] iterator dtor +// CHECK-NEXT: [A] iterator dtor +// CHECK-NEXT: [A] iterator advance: 0 += 0 +// CHECK-NEXT: [A] iterator move assign +// CHECK-NEXT: [A] iterator deref: 0 +// CHECK-NEXT: [B] iterator advance: 0 += 2 +// CHECK-NEXT: [B] iterator move assign +// CHECK-NEXT: [B] iterator deref: 2 +// CHECK-NEXT: i=0 v=0 w=2 +// CHECK-NEXT: [B] iterator dtor +// CHECK-NEXT: [A] iterator dtor +// CHECK-NEXT: [A] iterator advance: 0 += 1 +// CHECK-NEXT: [A] iterator move assign +// CHECK-NEXT: [A] iterator deref: 1 +// CHECK-NEXT: [B] iterator advance: 0 += 2 +// CHECK-NEXT: [B] iterator move assign +// CHECK-NEXT: [B] iterator deref: 2 +// CHECK-NEXT: i=0 v=1 w=2 +// CHECK-NEXT: [B] iterator dtor +// CHECK-NEXT: [A] iterator dtor +// CHECK-NEXT: [A] iterator advance: 0 += 2 +// CHECK-NEXT: [A] iterator move assign +// CHECK-NEXT: [A] iterator deref: 2 +// CHECK-NEXT: [B] iterator advance: 0 += 0 +// CHECK-NEXT: [B] iterator move assign +// CHECK-NEXT: [B] iterator deref: 0 +// CHECK-NEXT: i=0 v=2 w=0 +// CHECK-NEXT: [B] iterator dtor +// CHECK-NEXT: [B] iterator advance: 0 += 1 +// CHECK-NEXT: [B] iterator move assign +// CHECK-NEXT: [B] iterator deref: 1 +// CHECK-NEXT: i=0 v=2 w=1 +// CHECK-NEXT: [B] iterator dtor +// CHECK-NEXT: [A] iterator dtor +// CHECK-NEXT: [A] iterator advance: 0 += 2 +// CHECK-NEXT: [A] iterator move assign +// CHECK-NEXT: [A] iterator deref: 2 +// CHECK-NEXT: [B] iterator advance: 0 += 2 +// CHECK-NEXT: [B] iterator move assign +// CHECK-NEXT: [B] iterator deref: 2 +// CHECK-NEXT: i=0 v=2 w=2 +// CHECK-NEXT: [B] iterator dtor +// CHECK-NEXT: [A] iterator dtor +// CHECK-NEXT: [A] iterator advance: 0 += 0 +// CHECK-NEXT: [A] iterator move assign +// CHECK-NEXT: [A] iterator deref: 0 +// CHECK-NEXT: [B] iterator advance: 0 += 0 +// CHECK-NEXT: [B] iterator move assign +// CHECK-NEXT: [B] iterator deref: 0 +// CHECK-NEXT: i=1 v=0 w=0 +// CHECK-NEXT: [B] iterator dtor +// CHECK-NEXT: [B] iterator advance: 0 += 1 +// CHECK-NEXT: [B] iterator move assign +// CHECK-NEXT: [B] iterator deref: 1 +// CHECK-NEXT: i=1 v=0 w=1 +// CHECK-NEXT: [B] iterator dtor +// CHECK-NEXT: [A] iterator dtor +// CHECK-NEXT: [A] iterator advance: 0 += 1 +// CHECK-NEXT: [A] iterator move assign +// CHECK-NEXT: [A] iterator deref: 1 +// CHECK-NEXT: [B] iterator advance: 0 += 0 +// CHECK-NEXT: [B] iterator move assign +// CHECK-NEXT: [B] iterator deref: 0 +// CHECK-NEXT: i=1 v=1 w=0 +// CHECK-NEXT: [B] iterator dtor +// CHECK-NEXT: [B] iterator advance: 0 += 1 +// CHECK-NEXT: [B] iterator move assign +// CHECK-NEXT: [B] iterator deref: 1 +// CHECK-NEXT: i=1 v=1 w=1 +// CHECK-NEXT: [B] iterator dtor +// CHECK-NEXT: [A] iterator dtor +// CHECK-NEXT: [A] iterator advance: 0 += 0 +// CHECK-NEXT: [A] iterator move assign +// CHECK-NEXT: [A] iterator deref: 0 +// CHECK-NEXT: [B] iterator advance: 0 += 2 +// CHECK-NEXT: [B] iterator move assign +// CHECK-NEXT: [B] iterator deref: 2 +// CHECK-NEXT: i=1 v=0 w=2 +// CHECK-NEXT: [B] iterator dtor +// CHECK-NEXT: [A] iterator dtor +// CHECK-NEXT: [A] iterator advance: 0 += 1 +// CHECK-NEXT: [A] iterator move assign +// CHECK-NEXT: [A] iterator deref: 1 +// CHECK-NEXT: [B] iterator advance: 0 += 2 +// CHECK-NEXT: [B] iterator move assign +// CHECK-NEXT: [B] iterator deref: 2 +// CHECK-NEXT: i=1 v=1 w=2 +// CHECK-NEXT: [B] iterator dtor +// CHECK-NEXT: [A] iterator dtor +// CHECK-NEXT: [A] iterator advance: 0 += 2 +// CHECK-NEXT: [A] iterator move assign +// CHECK-NEXT: [A] iterator deref: 2 +// CHECK-NEXT: [B] iterator advance: 0 += 0 +// CHECK-NEXT: [B] iterator move assign +// CHECK-NEXT: [B] iterator deref: 0 +// CHECK-NEXT: i=1 v=2 w=0 +// CHECK-NEXT: [B] iterator dtor +// CHECK-NEXT: [B] iterator advance: 0 += 1 +// CHECK-NEXT: [B] iterator move assign +// CHECK-NEXT: [B] iterator deref: 1 +// CHECK-NEXT: i=1 v=2 w=1 +// CHECK-NEXT: [B] iterator dtor +// CHECK-NEXT: [A] iterator dtor +// CHECK-NEXT: [A] iterator advance: 0 += 2 +// CHECK-NEXT: [A] iterator move assign +// CHECK-NEXT: [A] iterator deref: 2 +// CHECK-NEXT: [B] iterator advance: 0 += 2 +// CHECK-NEXT: [B] iterator move assign +// CHECK-NEXT: [B] iterator deref: 2 +// CHECK-NEXT: i=1 v=2 w=2 +// CHECK-NEXT: [B] iterator dtor +// CHECK-NEXT: [A] iterator dtor +// CHECK-NEXT: [A] iterator advance: 0 += 0 +// CHECK-NEXT: [A] iterator move assign +// CHECK-NEXT: [A] iterator deref: 0 +// CHECK-NEXT: [B] iterator advance: 0 += 0 +// CHECK-NEXT: [B] iterator move assign +// CHECK-NEXT: [B] iterator deref: 0 +// CHECK-NEXT: i=2 v=0 w=0 +// CHECK-NEXT: [B] iterator dtor +// CHECK-NEXT: [B] iterator advance: 0 += 1 +// CHECK-NEXT: [B] iterator move assign +// CHECK-NEXT: [B] iterator deref: 1 +// CHECK-NEXT: i=2 v=0 w=1 +// CHECK-NEXT: [B] iterator dtor +// CHECK-NEXT: [A] iterator dtor +// CHECK-NEXT: [A] iterator advance: 0 += 1 +// CHECK-NEXT: [A] iterator move assign +// CHECK-NEXT: [A] iterator deref: 1 +// CHECK-NEXT: [B] iterator advance: 0 += 0 +// CHECK-NEXT: [B] iterator move assign +// CHECK-NEXT: [B] iterator deref: 0 +// CHECK-NEXT: i=2 v=1 w=0 +// CHECK-NEXT: [B] iterator dtor +// CHECK-NEXT: [B] iterator advance: 0 += 1 +// CHECK-NEXT: [B] iterator move assign +// CHECK-NEXT: [B] iterator deref: 1 +// CHECK-NEXT: i=2 v=1 w=1 +// CHECK-NEXT: [B] iterator dtor +// CHECK-NEXT: [A] iterator dtor +// CHECK-NEXT: [A] iterator advance: 0 += 0 +// CHECK-NEXT: [A] iterator move assign +// CHECK-NEXT: [A] iterator deref: 0 +// CHECK-NEXT: [B] iterator advance: 0 += 2 +// CHECK-NEXT: [B] iterator move assign +// CHECK-NEXT: [B] iterator deref: 2 +// CHECK-NEXT: i=2 v=0 w=2 +// CHECK-NEXT: [B] iterator dtor +// CHECK-NEXT: [A] iterator dtor +// CHECK-NEXT: [A] iterator advance: 0 += 1 +// CHECK-NEXT: [A] iterator move assign +// CHECK-NEXT: [A] iterator deref: 1 +// CHECK-NEXT: [B] iterator advance: 0 += 2 +// CHECK-NEXT: [B] iterator move assign +// CHECK-NEXT: [B] iterator deref: 2 +// CHECK-NEXT: i=2 v=1 w=2 +// CHECK-NEXT: [B] iterator dtor +// CHECK-NEXT: [A] iterator dtor +// CHECK-NEXT: [A] iterator advance: 0 += 2 +// CHECK-NEXT: [A] iterator move assign +// CHECK-NEXT: [A] iterator deref: 2 +// CHECK-NEXT: [B] iterator advance: 0 += 0 +// CHECK-NEXT: [B] iterator move assign +// CHECK-NEXT: [B] iterator deref: 0 +// CHECK-NEXT: i=2 v=2 w=0 +// CHECK-NEXT: [B] iterator dtor +// CHECK-NEXT: [B] iterator advance: 0 += 1 +// CHECK-NEXT: [B] iterator move assign +// CHECK-NEXT: [B] iterator deref: 1 +// CHECK-NEXT: i=2 v=2 w=1 +// CHECK-NEXT: [B] iterator dtor +// CHECK-NEXT: [A] iterator dtor +// CHECK-NEXT: [A] iterator advance: 0 += 2 +// CHECK-NEXT: [A] iterator move assign +// CHECK-NEXT: [A] iterator deref: 2 +// CHECK-NEXT: [B] iterator advance: 0 += 2 +// CHECK-NEXT: [B] iterator move assign +// CHECK-NEXT: [B] iterator deref: 2 +// CHECK-NEXT: i=2 v=2 w=2 +// CHECK-NEXT: [B] iterator dtor +// CHECK-NEXT: [A] iterator dtor +// CHECK-NEXT: [B] iterator dtor +// CHECK-NEXT: [B] iterator dtor +// CHECK-NEXT: [B] iterator dtor +// CHECK-NEXT: [B] dtor +// CHECK-NEXT: [D] dtor +// CHECK-NEXT: [A] iterator dtor +// CHECK-NEXT: [A] iterator dtor +// CHECK-NEXT: [A] iterator dtor +// CHECK-NEXT: [A] dtor +// CHECK-NEXT: [C] dtor +// CHECK-NEXT: done diff --git a/openmp/runtime/test/transform/unroll/factor_foreach.cpp b/openmp/runtime/test/transform/unroll/factor_foreach.cpp new file mode 100644 index 000000000000..29fef7c18736 --- /dev/null +++ b/openmp/runtime/test/transform/unroll/factor_foreach.cpp @@ -0,0 +1,162 @@ +// RUN: %libomp-cxx20-compile-and-run | FileCheck %s --match-full-lines + +#ifndef HEADER +#define HEADER + +#include +#include +#include +#include + +struct Reporter { + const char *name; + + Reporter(const char *name) : name(name) { print("ctor"); } + + Reporter() : name("") { print("ctor"); } + + Reporter(const Reporter &that) : name(that.name) { print("copy ctor"); } + + Reporter(Reporter &&that) : name(that.name) { print("move ctor"); } + + ~Reporter() { print("dtor"); } + + const Reporter &operator=(const Reporter &that) { + print("copy assign"); + this->name = that.name; + return *this; + } + + const Reporter &operator=(Reporter &&that) { + print("move assign"); + this->name = that.name; + return *this; + } + + struct Iterator { + const Reporter *owner; + int pos; + + Iterator(const Reporter *owner, int pos) : owner(owner), pos(pos) {} + + Iterator(const Iterator &that) : owner(that.owner), pos(that.pos) { + owner->print("iterator copy ctor"); + } + + Iterator(Iterator &&that) : owner(that.owner), pos(that.pos) { + owner->print("iterator move ctor"); + } + + ~Iterator() { owner->print("iterator dtor"); } + + const Iterator &operator=(const Iterator &that) { + owner->print("iterator copy assign"); + this->owner = that.owner; + this->pos = that.pos; + return *this; + } + + const Iterator &operator=(Iterator &&that) { + owner->print("iterator move assign"); + this->owner = that.owner; + this->pos = that.pos; + return *this; + } + + bool operator==(const Iterator &that) const { + owner->print("iterator %d == %d", 2 - this->pos, 2 - that.pos); + return this->pos == that.pos; + } + + bool operator!=(const Iterator &that) const { + owner->print("iterator %d != %d", 2 - this->pos, 2 - that.pos); + return this->pos != that.pos; + } + + Iterator &operator++() { + owner->print("iterator prefix ++"); + pos -= 1; + return *this; + } + + Iterator operator++(int) { + owner->print("iterator postfix ++"); + auto result = *this; + pos -= 1; + return result; + } + + int operator*() const { + int result = 2 - pos; + owner->print("iterator deref: %i", result); + return result; + } + + size_t operator-(const Iterator &that) const { + int result = (2 - this->pos) - (2 - that.pos); + owner->print("iterator distance: %d", result); + return result; + } + + Iterator operator+(int steps) const { + owner->print("iterator advance: %i += %i", 2 - this->pos, steps); + return Iterator(owner, pos - steps); + } + + void print(const char *msg) const { owner->print(msg); } + }; + + Iterator begin() const { + print("begin()"); + return Iterator(this, 2); + } + + Iterator end() const { + print("end()"); + return Iterator(this, -1); + } + + void print(const char *msg, ...) const { + va_list args; + va_start(args, msg); + printf("[%s] ", name); + vprintf(msg, args); + printf("\n"); + va_end(args); + } +}; + +int main() { + printf("do\n"); +#pragma omp unroll partial(2) + for (Reporter c{"init-stmt"}; auto &&v : Reporter("range")) + printf("v=%d\n", v); + printf("done\n"); + return EXIT_SUCCESS; +} + +#endif /* HEADER */ + +// CHECK: do +// CHECK-NEXT: [init-stmt] ctor +// CHECK-NEXT: [range] ctor +// CHECK-NEXT: [range] begin() +// CHECK-NEXT: [range] end() +// CHECK-NEXT: [range] iterator 0 != 3 +// CHECK-NEXT: [range] iterator deref: 0 +// CHECK-NEXT: v=0 +// CHECK-NEXT: [range] iterator prefix ++ +// CHECK-NEXT: [range] iterator 1 != 3 +// CHECK-NEXT: [range] iterator deref: 1 +// CHECK-NEXT: v=1 +// CHECK-NEXT: [range] iterator prefix ++ +// CHECK-NEXT: [range] iterator 2 != 3 +// CHECK-NEXT: [range] iterator deref: 2 +// CHECK-NEXT: v=2 +// CHECK-NEXT: [range] iterator prefix ++ +// CHECK-NEXT: [range] iterator 3 != 3 +// CHECK-NEXT: [range] iterator dtor +// CHECK-NEXT: [range] iterator dtor +// CHECK-NEXT: [range] dtor +// CHECK-NEXT: [init-stmt] dtor +// CHECK-NEXT: done diff --git a/openmp/runtime/test/transform/unroll/factor_intfor.c b/openmp/runtime/test/transform/unroll/factor_intfor.c new file mode 100644 index 000000000000..42ebeb48e41c --- /dev/null +++ b/openmp/runtime/test/transform/unroll/factor_intfor.c @@ -0,0 +1,25 @@ +// RUN: %libomp-compile-and-run | FileCheck %s --match-full-lines + +#ifndef HEADER +#define HEADER + +#include +#include + +int main() { + printf("do\n"); +#pragma omp unroll partial(2) + for (int i = 7; i < 19; i += 3) + printf("i=%d\n", i); + printf("done\n"); + return EXIT_SUCCESS; +} + +#endif /* HEADER */ + +// CHECK: do +// CHECK-NEXT: i=7 +// CHECK-NEXT: i=10 +// CHECK-NEXT: i=13 +// CHECK-NEXT: i=16 +// CHECK-NEXT: done diff --git a/openmp/runtime/test/transform/unroll/factor_iterfor.cpp b/openmp/runtime/test/transform/unroll/factor_iterfor.cpp new file mode 100644 index 000000000000..0298477110b2 --- /dev/null +++ b/openmp/runtime/test/transform/unroll/factor_iterfor.cpp @@ -0,0 +1,169 @@ +// RUN: %libomp-cxx20-compile-and-run | FileCheck %s --match-full-lines + +#ifndef HEADER +#define HEADER + +#include +#include +#include +#include + +struct Reporter { + const char *name; + + Reporter(const char *name) : name(name) { print("ctor"); } + + Reporter() : name("") { print("ctor"); } + + Reporter(const Reporter &that) : name(that.name) { print("copy ctor"); } + + Reporter(Reporter &&that) : name(that.name) { print("move ctor"); } + + ~Reporter() { print("dtor"); } + + const Reporter &operator=(const Reporter &that) { + print("copy assign"); + this->name = that.name; + return *this; + } + + const Reporter &operator=(Reporter &&that) { + print("move assign"); + this->name = that.name; + return *this; + } + + struct Iterator { + const Reporter *owner; + int pos; + + Iterator(const Reporter *owner, int pos) : owner(owner), pos(pos) {} + + Iterator(const Iterator &that) : owner(that.owner), pos(that.pos) { + print("iterator copy ctor"); + } + + Iterator(Iterator &&that) : owner(that.owner), pos(that.pos) { + print("iterator move ctor"); + } + + ~Iterator() { print("iterator dtor"); } + + const Iterator &operator=(const Iterator &that) { + print("iterator copy assign"); + this->owner = that.owner; + this->pos = that.pos; + return *this; + } + + const Iterator &operator=(Iterator &&that) { + print("iterator move assign"); + this->owner = that.owner; + this->pos = that.pos; + return *this; + } + + bool operator==(const Iterator &that) const { + owner->print("iterator %d == %d", 2 - this->pos, 2 - that.pos); + return this->pos == that.pos; + } + + bool operator!=(const Iterator &that) const { + owner->print("iterator %d != %d", 2 - this->pos, 2 - that.pos); + return this->pos != that.pos; + } + + Iterator &operator++() { + print("iterator prefix ++"); + pos -= 1; + return *this; + } + + Iterator operator++(int) { + print("iterator postfix ++"); + auto result = *this; + pos -= 1; + return result; + } + + int operator*() const { + int result = 2 - pos; + owner->print("iterator deref: %i", result); + return result; + } + + size_t operator-(const Iterator &that) const { + int result = (2 - this->pos) - (2 - that.pos); + owner->print("iterator distance: %d", result); + return result; + } + + Iterator operator+(int steps) const { + owner->print("iterator advance: %i += %i", 2 - this->pos, steps); + return Iterator(owner, pos - steps); + } + + void print(const char *msg) const { owner->print(msg); } + }; + + Iterator begin() const { + print("begin()"); + return Iterator(this, 2); + } + + Iterator end() const { + print("end()"); + return Iterator(this, -1); + } + + void print(const char *msg, ...) const { + va_list args; + va_start(args, msg); + printf("[%s] ", name); + vprintf(msg, args); + printf("\n"); + va_end(args); + } +}; + +int main() { + printf("do\n"); + { + Reporter range("range"); +#pragma omp unroll partial(2) + for (auto it = range.begin(); it != range.end(); ++it) + printf("v=%d\n", *it); + } + printf("done\n"); + return EXIT_SUCCESS; +} + +#endif /* HEADER */ + +// CHECK: do +// CHECK-NEXT: [range] ctor +// CHECK-NEXT: [range] begin() +// CHECK-NEXT: [range] end() +// CHECK-NEXT: [range] iterator 0 != 3 +// CHECK-NEXT: [range] iterator deref: 0 +// CHECK-NEXT: v=0 +// CHECK-NEXT: [range] iterator prefix ++ +// CHECK-NEXT: [range] iterator dtor +// CHECK-NEXT: [range] end() +// CHECK-NEXT: [range] iterator 1 != 3 +// CHECK-NEXT: [range] iterator deref: 1 +// CHECK-NEXT: v=1 +// CHECK-NEXT: [range] iterator prefix ++ +// CHECK-NEXT: [range] iterator dtor +// CHECK-NEXT: [range] end() +// CHECK-NEXT: [range] iterator 2 != 3 +// CHECK-NEXT: [range] iterator deref: 2 +// CHECK-NEXT: v=2 +// CHECK-NEXT: [range] iterator prefix ++ +// CHECK-NEXT: [range] iterator dtor +// CHECK-NEXT: [range] end() +// CHECK-NEXT: [range] iterator 3 != 3 +// CHECK-NEXT: [range] iterator dtor +// CHECK-NEXT: [range] iterator dtor +// CHECK-NEXT: [range] dtor +// CHECK-NEXT: done diff --git a/openmp/runtime/test/transform/unroll/factor_parallel-wsloop-collapse-foreach.cpp b/openmp/runtime/test/transform/unroll/factor_parallel-wsloop-collapse-foreach.cpp new file mode 100644 index 000000000000..71567faf7964 --- /dev/null +++ b/openmp/runtime/test/transform/unroll/factor_parallel-wsloop-collapse-foreach.cpp @@ -0,0 +1,199 @@ +// RUN: %libomp-cxx20-compile-and-run | FileCheck %s --match-full-lines + +#ifndef HEADER +#define HEADER + +#include +#include +#include +#include + +struct Reporter { + const char *name; + + Reporter(const char *name) : name(name) { print("ctor"); } + + Reporter() : name("") { print("ctor"); } + + Reporter(const Reporter &that) : name(that.name) { print("copy ctor"); } + + Reporter(Reporter &&that) : name(that.name) { print("move ctor"); } + + ~Reporter() { print("dtor"); } + + const Reporter &operator=(const Reporter &that) { + print("copy assign"); + this->name = that.name; + return *this; + } + + const Reporter &operator=(Reporter &&that) { + print("move assign"); + this->name = that.name; + return *this; + } + + struct Iterator { + const Reporter *owner; + int pos; + + Iterator(const Reporter *owner, int pos) : owner(owner), pos(pos) {} + + Iterator(const Iterator &that) : owner(that.owner), pos(that.pos) { + owner->print("iterator copy ctor"); + } + + Iterator(Iterator &&that) : owner(that.owner), pos(that.pos) { + owner->print("iterator move ctor"); + } + + ~Iterator() { owner->print("iterator dtor"); } + + const Iterator &operator=(const Iterator &that) { + owner->print("iterator copy assign"); + this->owner = that.owner; + this->pos = that.pos; + return *this; + } + + const Iterator &operator=(Iterator &&that) { + owner->print("iterator move assign"); + this->owner = that.owner; + this->pos = that.pos; + return *this; + } + + bool operator==(const Iterator &that) const { + owner->print("iterator %d == %d", 2 - this->pos, 2 - that.pos); + return this->pos == that.pos; + } + + bool operator!=(const Iterator &that) const { + owner->print("iterator %d != %d", 2 - this->pos, 2 - that.pos); + return this->pos != that.pos; + } + + Iterator &operator++() { + owner->print("iterator prefix ++"); + pos -= 1; + return *this; + } + + Iterator operator++(int) { + owner->print("iterator postfix ++"); + auto result = *this; + pos -= 1; + return result; + } + + int operator*() const { + int result = 2 - pos; + owner->print("iterator deref: %i", result); + return result; + } + + size_t operator-(const Iterator &that) const { + int result = (2 - this->pos) - (2 - that.pos); + owner->print("iterator distance: %d", result); + return result; + } + + Iterator operator+(int steps) const { + owner->print("iterator advance: %i += %i", 2 - this->pos, steps); + return Iterator(owner, pos - steps); + } + + void print(const char *msg) const { owner->print(msg); } + }; + + Iterator begin() const { + print("begin()"); + return Iterator(this, 2); + } + + Iterator end() const { + print("end()"); + return Iterator(this, -1); + } + + void print(const char *msg, ...) const { + va_list args; + va_start(args, msg); + printf("[%s] ", name); + vprintf(msg, args); + printf("\n"); + va_end(args); + } +}; + +int main() { + printf("do\n"); +#pragma omp parallel for collapse(2) num_threads(1) + for (int i = 0; i < 3; ++i) +#pragma omp unroll partial(2) + for (Reporter c{"init-stmt"}; auto &&v : Reporter("range")) + printf("i=%d v=%d\n", i, v); + printf("done\n"); + return EXIT_SUCCESS; +} + +#endif /* HEADER */ + +// CHECK: do +// CHECK-NEXT: [init-stmt] ctor +// CHECK-NEXT: [range] ctor +// CHECK-NEXT: [range] end() +// CHECK-NEXT: [range] begin() +// CHECK-NEXT: [range] begin() +// CHECK-NEXT: [range] iterator distance: 3 +// CHECK-NEXT: [range] iterator advance: 0 += 0 +// CHECK-NEXT: [range] iterator move assign +// CHECK-NEXT: [range] iterator deref: 0 +// CHECK-NEXT: i=0 v=0 +// CHECK-NEXT: [range] iterator dtor +// CHECK-NEXT: [range] iterator advance: 0 += 1 +// CHECK-NEXT: [range] iterator move assign +// CHECK-NEXT: [range] iterator deref: 1 +// CHECK-NEXT: i=0 v=1 +// CHECK-NEXT: [range] iterator dtor +// CHECK-NEXT: [range] iterator advance: 0 += 2 +// CHECK-NEXT: [range] iterator move assign +// CHECK-NEXT: [range] iterator deref: 2 +// CHECK-NEXT: i=0 v=2 +// CHECK-NEXT: [range] iterator dtor +// CHECK-NEXT: [range] iterator advance: 0 += 0 +// CHECK-NEXT: [range] iterator move assign +// CHECK-NEXT: [range] iterator deref: 0 +// CHECK-NEXT: i=1 v=0 +// CHECK-NEXT: [range] iterator dtor +// CHECK-NEXT: [range] iterator advance: 0 += 1 +// CHECK-NEXT: [range] iterator move assign +// CHECK-NEXT: [range] iterator deref: 1 +// CHECK-NEXT: i=1 v=1 +// CHECK-NEXT: [range] iterator dtor +// CHECK-NEXT: [range] iterator advance: 0 += 2 +// CHECK-NEXT: [range] iterator move assign +// CHECK-NEXT: [range] iterator deref: 2 +// CHECK-NEXT: i=1 v=2 +// CHECK-NEXT: [range] iterator dtor +// CHECK-NEXT: [range] iterator advance: 0 += 0 +// CHECK-NEXT: [range] iterator move assign +// CHECK-NEXT: [range] iterator deref: 0 +// CHECK-NEXT: i=2 v=0 +// CHECK-NEXT: [range] iterator dtor +// CHECK-NEXT: [range] iterator advance: 0 += 1 +// CHECK-NEXT: [range] iterator move assign +// CHECK-NEXT: [range] iterator deref: 1 +// CHECK-NEXT: i=2 v=1 +// CHECK-NEXT: [range] iterator dtor +// CHECK-NEXT: [range] iterator advance: 0 += 2 +// CHECK-NEXT: [range] iterator move assign +// CHECK-NEXT: [range] iterator deref: 2 +// CHECK-NEXT: i=2 v=2 +// CHECK-NEXT: [range] iterator dtor +// CHECK-NEXT: [range] iterator dtor +// CHECK-NEXT: [range] iterator dtor +// CHECK-NEXT: [range] iterator dtor +// CHECK-NEXT: [range] dtor +// CHECK-NEXT: [init-stmt] dtor +// CHECK-NEXT: done diff --git a/openmp/runtime/test/transform/unroll/factor_parallel-wsloop-collapse-intfor.cpp b/openmp/runtime/test/transform/unroll/factor_parallel-wsloop-collapse-intfor.cpp new file mode 100644 index 000000000000..0a31f8db0701 --- /dev/null +++ b/openmp/runtime/test/transform/unroll/factor_parallel-wsloop-collapse-intfor.cpp @@ -0,0 +1,32 @@ +// RUN: %libomp-cxx-compile-and-run | FileCheck %s --match-full-lines + +#ifndef HEADER +#define HEADER + +#include +#include + +int main() { + printf("do\n"); +#pragma omp parallel for collapse(2) num_threads(1) + for (int i = 0; i < 3; ++i) +#pragma omp unroll partial(2) + for (int j = 0; j < 3; ++j) + printf("i=%d j=%d\n", i, j); + printf("done\n"); + return EXIT_SUCCESS; +} + +#endif /* HEADER */ + +// CHECK: do +// CHECK-NEXT: i=0 j=0 +// CHECK-NEXT: i=0 j=1 +// CHECK-NEXT: i=0 j=2 +// CHECK-NEXT: i=1 j=0 +// CHECK-NEXT: i=1 j=1 +// CHECK-NEXT: i=1 j=2 +// CHECK-NEXT: i=2 j=0 +// CHECK-NEXT: i=2 j=1 +// CHECK-NEXT: i=2 j=2 +// CHECK-NEXT: done diff --git a/openmp/runtime/test/transform/unroll/full_intfor.c b/openmp/runtime/test/transform/unroll/full_intfor.c new file mode 100644 index 000000000000..081451109176 --- /dev/null +++ b/openmp/runtime/test/transform/unroll/full_intfor.c @@ -0,0 +1,25 @@ +// RUN: %libomp-compile-and-run | FileCheck %s --match-full-lines + +#ifndef HEADER +#define HEADER + +#include +#include + +int main() { + printf("do\n"); +#pragma omp unroll full + for (int i = 7; i < 19; i += 3) + printf("i=%d\n", i); + printf("done\n"); + return EXIT_SUCCESS; +} + +#endif /* HEADER */ + +// CHECK: do +// CHECK-NEXT: i=7 +// CHECK-NEXT: i=10 +// CHECK-NEXT: i=13 +// CHECK-NEXT: i=16 +// CHECK-NEXT: done diff --git a/openmp/runtime/test/transform/unroll/heuristic_intfor.c b/openmp/runtime/test/transform/unroll/heuristic_intfor.c new file mode 100644 index 000000000000..b07bec7d82f0 --- /dev/null +++ b/openmp/runtime/test/transform/unroll/heuristic_intfor.c @@ -0,0 +1,25 @@ +// RUN: %libomp-compile-and-run | FileCheck %s --match-full-lines + +#ifndef HEADER +#define HEADER + +#include +#include + +int main() { + printf("do\n"); +#pragma omp unroll + for (int i = 7; i < 19; i += 3) + printf("i=%d\n", i); + printf("done\n"); + return EXIT_SUCCESS; +} + +#endif /* HEADER */ + +// CHECK: do +// CHECK-NEXT: i=7 +// CHECK-NEXT: i=10 +// CHECK-NEXT: i=13 +// CHECK-NEXT: i=16 +// CHECK-NEXT: done diff --git a/openmp/runtime/test/transform/unroll/partial_intfor.c b/openmp/runtime/test/transform/unroll/partial_intfor.c new file mode 100644 index 000000000000..2ede94e70e12 --- /dev/null +++ b/openmp/runtime/test/transform/unroll/partial_intfor.c @@ -0,0 +1,25 @@ +// RUN: %libomp-compile-and-run | FileCheck %s --match-full-lines + +#ifndef HEADER +#define HEADER + +#include +#include + +int main() { + printf("do\n"); +#pragma omp unroll partial + for (int i = 7; i < 19; i += 3) + printf("i=%d\n", i); + printf("done\n"); + return EXIT_SUCCESS; +} + +#endif /* HEADER */ + +// CHECK: do +// CHECK-NEXT: i=7 +// CHECK-NEXT: i=10 +// CHECK-NEXT: i=13 +// CHECK-NEXT: i=16 +// CHECK-NEXT: done -- GitLab From 0748a98ab009d4fd97438970e7d92660967a0652 Mon Sep 17 00:00:00 2001 From: Nikita Popov Date: Wed, 22 May 2024 14:33:06 +0200 Subject: [PATCH 116/452] [InstCombine] Handle ConstantFoldCompareInstOperands() failure This function will return nullptr instead of returning a constant expression now, so be sure to handle that. Fixes https://github.com/llvm/llvm-project/issues/93017. --- .../InstCombine/InstCombineCompares.cpp | 3 +++ llvm/test/Transforms/InstCombine/load-cmp.ll | 17 +++++++++++++++++ 2 files changed, 20 insertions(+) diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp index 542a1c82b127..430f3e12fa5b 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp @@ -214,6 +214,9 @@ Instruction *InstCombinerImpl::foldCmpLoadFromIndexedGlobal( // Find out if the comparison would be true or false for the i'th element. Constant *C = ConstantFoldCompareInstOperands(ICI.getPredicate(), Elt, CompareRHS, DL, &TLI); + if (!C) + return nullptr; + // If the result is undef for this element, ignore it. if (isa(C)) { // Extend range state machines to cover this element in case there is an diff --git a/llvm/test/Transforms/InstCombine/load-cmp.ll b/llvm/test/Transforms/InstCombine/load-cmp.ll index e941284a798e..b956de29e0b8 100644 --- a/llvm/test/Transforms/InstCombine/load-cmp.ll +++ b/llvm/test/Transforms/InstCombine/load-cmp.ll @@ -334,3 +334,20 @@ define i1 @test10_struct_arr_noinbounds_i64(i64 %x) { %r = icmp eq i32 %q, 9 ret i1 %r } + +@table = internal constant [2 x ptr] [ptr @g, ptr getelementptr (i8, ptr @g, i64 4)], align 16 +@g = external global [2 x i32] + +define i1 @pr93017(i64 %idx) { +; CHECK-LABEL: @pr93017( +; CHECK-NEXT: [[TMP1:%.*]] = trunc i64 [[IDX:%.*]] to i32 +; CHECK-NEXT: [[GEP:%.*]] = getelementptr inbounds [2 x ptr], ptr @table, i32 0, i32 [[TMP1]] +; CHECK-NEXT: [[V:%.*]] = load ptr, ptr [[GEP]], align 4 +; CHECK-NEXT: [[CMP:%.*]] = icmp ne ptr [[V]], null +; CHECK-NEXT: ret i1 [[CMP]] +; + %gep = getelementptr inbounds [2 x ptr], ptr @table, i64 0, i64 %idx + %v = load ptr, ptr %gep + %cmp = icmp ne ptr %v, null + ret i1 %cmp +} -- GitLab From cdcd65350bdeafccda33a5d4185c04f4bbe59495 Mon Sep 17 00:00:00 2001 From: Simon Pilgrim Date: Wed, 22 May 2024 13:41:07 +0100 Subject: [PATCH 117/452] [X86] combineBitcast - merge isa<>/cast<> into single dyn_cast<> call. NFC. --- llvm/lib/Target/X86/X86ISelLowering.cpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/llvm/lib/Target/X86/X86ISelLowering.cpp b/llvm/lib/Target/X86/X86ISelLowering.cpp index 24ee0c45b667..37c591f90f0a 100644 --- a/llvm/lib/Target/X86/X86ISelLowering.cpp +++ b/llvm/lib/Target/X86/X86ISelLowering.cpp @@ -43694,14 +43694,14 @@ static SDValue combineBitcast(SDNode *N, SelectionDAG &DAG, return combinevXi1ConstantToInteger(N0, DAG); } - if (Subtarget.hasAVX512() && SrcVT.isScalarInteger() && - VT.isVector() && VT.getVectorElementType() == MVT::i1 && - isa(N0)) { - auto *C = cast(N0); - if (C->isAllOnes()) - return DAG.getConstant(1, SDLoc(N0), VT); - if (C->isZero()) - return DAG.getConstant(0, SDLoc(N0), VT); + if (Subtarget.hasAVX512() && SrcVT.isScalarInteger() && VT.isVector() && + VT.getVectorElementType() == MVT::i1) { + if (auto *C = dyn_cast(N0)) { + if (C->isAllOnes()) + return DAG.getConstant(1, SDLoc(N0), VT); + if (C->isZero()) + return DAG.getConstant(0, SDLoc(N0), VT); + } } // Look for MOVMSK that is maybe truncated and then bitcasted to vXi1. -- GitLab From a699ccbf0c2d4bc5c912e096a8834cf4e04ce98b Mon Sep 17 00:00:00 2001 From: Janek van Oirschot Date: Wed, 22 May 2024 13:45:45 +0100 Subject: [PATCH 118/452] MCExpr-ify amd_kernel_code_t (#91587) Redefines the amd_kernel_code_t struct with MCExprs for members that would be derived from SIProgramInfo MCExpr members. --- llvm/lib/Target/AMDGPU/AMDGPUAsmPrinter.cpp | 32 +- llvm/lib/Target/AMDGPU/AMDGPUAsmPrinter.h | 6 +- .../AMDGPU/AsmParser/AMDGPUAsmParser.cpp | 51 +- .../MCTargetDesc/AMDGPUTargetStreamer.cpp | 12 +- .../MCTargetDesc/AMDGPUTargetStreamer.h | 9 +- llvm/lib/Target/AMDGPU/SIDefines.h | 2 +- .../Target/AMDGPU/Utils/AMDGPUBaseInfo.cpp | 45 +- llvm/lib/Target/AMDGPU/Utils/AMDGPUBaseInfo.h | 3 +- .../Target/AMDGPU/Utils/AMDKernelCodeTInfo.h | 35 +- .../AMDGPU/Utils/AMDKernelCodeTUtils.cpp | 540 +++++++++++++++--- .../Target/AMDGPU/Utils/AMDKernelCodeTUtils.h | 79 ++- llvm/lib/Target/AMDGPU/Utils/CMakeLists.txt | 1 + .../CodeGen/AMDGPU/kernel_code_t_recurse.ll | 24 + llvm/test/MC/AMDGPU/amd_kernel_code_t.s | 171 ++++++ 14 files changed, 831 insertions(+), 179 deletions(-) create mode 100644 llvm/test/CodeGen/AMDGPU/kernel_code_t_recurse.ll create mode 100644 llvm/test/MC/AMDGPU/amd_kernel_code_t.s diff --git a/llvm/lib/Target/AMDGPU/AMDGPUAsmPrinter.cpp b/llvm/lib/Target/AMDGPU/AMDGPUAsmPrinter.cpp index bd48a5f80c82..cad4a3430327 100644 --- a/llvm/lib/Target/AMDGPU/AMDGPUAsmPrinter.cpp +++ b/llvm/lib/Target/AMDGPU/AMDGPUAsmPrinter.cpp @@ -19,7 +19,6 @@ #include "AMDGPU.h" #include "AMDGPUHSAMetadataStreamer.h" #include "AMDGPUResourceUsageAnalysis.h" -#include "AMDKernelCodeT.h" #include "GCNSubtarget.h" #include "MCTargetDesc/AMDGPUInstPrinter.h" #include "MCTargetDesc/AMDGPUMCExpr.h" @@ -29,6 +28,7 @@ #include "SIMachineFunctionInfo.h" #include "TargetInfo/AMDGPUTargetInfo.h" #include "Utils/AMDGPUBaseInfo.h" +#include "Utils/AMDKernelCodeTUtils.h" #include "llvm/Analysis/OptimizationRemarkEmitter.h" #include "llvm/BinaryFormat/ELF.h" #include "llvm/CodeGen/MachineFrameInfo.h" @@ -205,8 +205,9 @@ void AMDGPUAsmPrinter::emitFunctionBodyStart() { if (STM.isMesaKernel(F) && (F.getCallingConv() == CallingConv::AMDGPU_KERNEL || F.getCallingConv() == CallingConv::SPIR_KERNEL)) { - amd_kernel_code_t KernelCode; + AMDGPUMCKernelCodeT KernelCode; getAmdKernelCode(KernelCode, CurrentProgramInfo, *MF); + KernelCode.validate(&STM, MF->getContext()); getTargetStreamer()->EmitAMDKernelCodeT(KernelCode); } @@ -1317,7 +1318,7 @@ static amd_element_byte_size_t getElementByteSizeValue(unsigned Size) { } } -void AMDGPUAsmPrinter::getAmdKernelCode(amd_kernel_code_t &Out, +void AMDGPUAsmPrinter::getAmdKernelCode(AMDGPUMCKernelCodeT &Out, const SIProgramInfo &CurrentProgramInfo, const MachineFunction &MF) const { const Function &F = MF.getFunction(); @@ -1328,24 +1329,22 @@ void AMDGPUAsmPrinter::getAmdKernelCode(amd_kernel_code_t &Out, const GCNSubtarget &STM = MF.getSubtarget(); MCContext &Ctx = MF.getContext(); - AMDGPU::initDefaultAMDKernelCodeT(Out, &STM); + Out.initDefault(&STM, Ctx, /*InitMCExpr=*/false); - Out.compute_pgm_resource_registers = - CurrentProgramInfo.getComputePGMRSrc1(STM) | - (CurrentProgramInfo.getComputePGMRSrc2() << 32); + Out.compute_pgm_resource1_registers = + CurrentProgramInfo.getComputePGMRSrc1(STM, Ctx); + Out.compute_pgm_resource2_registers = + CurrentProgramInfo.getComputePGMRSrc2(Ctx); Out.code_properties |= AMD_CODE_PROPERTY_IS_PTR64; - if (getMCExprValue(CurrentProgramInfo.DynamicCallStack, Ctx)) - Out.code_properties |= AMD_CODE_PROPERTY_IS_DYNAMIC_CALLSTACK; + Out.is_dynamic_callstack = CurrentProgramInfo.DynamicCallStack; - AMD_HSA_BITS_SET(Out.code_properties, - AMD_CODE_PROPERTY_PRIVATE_ELEMENT_SIZE, + AMD_HSA_BITS_SET(Out.code_properties, AMD_CODE_PROPERTY_PRIVATE_ELEMENT_SIZE, getElementByteSizeValue(STM.getMaxPrivateElementSize(true))); const GCNUserSGPRUsageInfo &UserSGPRInfo = MFI->getUserSGPRInfo(); if (UserSGPRInfo.hasPrivateSegmentBuffer()) { - Out.code_properties |= - AMD_CODE_PROPERTY_ENABLE_SGPR_PRIVATE_SEGMENT_BUFFER; + Out.code_properties |= AMD_CODE_PROPERTY_ENABLE_SGPR_PRIVATE_SEGMENT_BUFFER; } if (UserSGPRInfo.hasDispatchPtr()) @@ -1371,10 +1370,9 @@ void AMDGPUAsmPrinter::getAmdKernelCode(amd_kernel_code_t &Out, Align MaxKernArgAlign; Out.kernarg_segment_byte_size = STM.getKernArgSegmentSize(F, MaxKernArgAlign); - Out.wavefront_sgpr_count = getMCExprValue(CurrentProgramInfo.NumSGPR, Ctx); - Out.workitem_vgpr_count = getMCExprValue(CurrentProgramInfo.NumVGPR, Ctx); - Out.workitem_private_segment_byte_size = - getMCExprValue(CurrentProgramInfo.ScratchSize, Ctx); + Out.wavefront_sgpr_count = CurrentProgramInfo.NumSGPR; + Out.workitem_vgpr_count = CurrentProgramInfo.NumVGPR; + Out.workitem_private_segment_byte_size = CurrentProgramInfo.ScratchSize; Out.workgroup_group_segment_byte_size = CurrentProgramInfo.LDSSize; // kernarg_segment_alignment is specified as log of the alignment. diff --git a/llvm/lib/Target/AMDGPU/AMDGPUAsmPrinter.h b/llvm/lib/Target/AMDGPU/AMDGPUAsmPrinter.h index 16d8952a533e..87156f27fc6c 100644 --- a/llvm/lib/Target/AMDGPU/AMDGPUAsmPrinter.h +++ b/llvm/lib/Target/AMDGPU/AMDGPUAsmPrinter.h @@ -17,8 +17,6 @@ #include "SIProgramInfo.h" #include "llvm/CodeGen/AsmPrinter.h" -struct amd_kernel_code_t; - namespace llvm { class AMDGPUMachineFunction; @@ -29,6 +27,7 @@ class MCOperand; namespace AMDGPU { struct MCKernelDescriptor; +struct AMDGPUMCKernelCodeT; namespace HSAMD { class MetadataStreamer; } @@ -50,7 +49,8 @@ private: uint64_t getFunctionCodeSize(const MachineFunction &MF) const; void getSIProgramInfo(SIProgramInfo &Out, const MachineFunction &MF); - void getAmdKernelCode(amd_kernel_code_t &Out, const SIProgramInfo &KernelInfo, + void getAmdKernelCode(AMDGPU::AMDGPUMCKernelCodeT &Out, + const SIProgramInfo &KernelInfo, const MachineFunction &MF) const; /// Emit register usage information so that the GPU driver diff --git a/llvm/lib/Target/AMDGPU/AsmParser/AMDGPUAsmParser.cpp b/llvm/lib/Target/AMDGPU/AsmParser/AMDGPUAsmParser.cpp index c08c35c45984..dcd4b22f4057 100644 --- a/llvm/lib/Target/AMDGPU/AsmParser/AMDGPUAsmParser.cpp +++ b/llvm/lib/Target/AMDGPU/AsmParser/AMDGPUAsmParser.cpp @@ -1340,7 +1340,7 @@ private: bool ParseDirectiveAMDGCNTarget(); bool ParseDirectiveAMDHSACodeObjectVersion(); bool ParseDirectiveAMDHSAKernel(); - bool ParseAMDKernelCodeTValue(StringRef ID, amd_kernel_code_t &Header); + bool ParseAMDKernelCodeTValue(StringRef ID, AMDGPUMCKernelCodeT &Header); bool ParseDirectiveAMDKernelCodeT(); // TODO: Possibly make subtargetHasRegister const. bool subtargetHasRegister(const MCRegisterInfo &MRI, unsigned RegNo); @@ -5863,7 +5863,7 @@ bool AMDGPUAsmParser::ParseDirectiveAMDHSACodeObjectVersion() { } bool AMDGPUAsmParser::ParseAMDKernelCodeTValue(StringRef ID, - amd_kernel_code_t &Header) { + AMDGPUMCKernelCodeT &C) { // max_scratch_backing_memory_byte_size is deprecated. Ignore it while parsing // assembly for backwards compatibility. if (ID == "max_scratch_backing_memory_byte_size") { @@ -5873,25 +5873,13 @@ bool AMDGPUAsmParser::ParseAMDKernelCodeTValue(StringRef ID, SmallString<40> ErrStr; raw_svector_ostream Err(ErrStr); - if (!parseAmdKernelCodeField(ID, getParser(), Header, Err)) { + if (!C.ParseKernelCodeT(ID, getParser(), Err)) { return TokError(Err.str()); } Lex(); - if (ID == "enable_dx10_clamp") { - if (G_00B848_DX10_CLAMP(Header.compute_pgm_resource_registers) && - isGFX12Plus()) - return TokError("enable_dx10_clamp=1 is not allowed on GFX12+"); - } - - if (ID == "enable_ieee_mode") { - if (G_00B848_IEEE_MODE(Header.compute_pgm_resource_registers) && - isGFX12Plus()) - return TokError("enable_ieee_mode=1 is not allowed on GFX12+"); - } - if (ID == "enable_wavefront_size32") { - if (Header.code_properties & AMD_CODE_PROPERTY_ENABLE_WAVEFRONT_SIZE32) { + if (C.code_properties & AMD_CODE_PROPERTY_ENABLE_WAVEFRONT_SIZE32) { if (!isGFX10Plus()) return TokError("enable_wavefront_size32=1 is only allowed on GFX10+"); if (!getFeatureBits()[AMDGPU::FeatureWavefrontSize32]) @@ -5903,41 +5891,23 @@ bool AMDGPUAsmParser::ParseAMDKernelCodeTValue(StringRef ID, } if (ID == "wavefront_size") { - if (Header.wavefront_size == 5) { + if (C.wavefront_size == 5) { if (!isGFX10Plus()) return TokError("wavefront_size=5 is only allowed on GFX10+"); if (!getFeatureBits()[AMDGPU::FeatureWavefrontSize32]) return TokError("wavefront_size=5 requires +WavefrontSize32"); - } else if (Header.wavefront_size == 6) { + } else if (C.wavefront_size == 6) { if (!getFeatureBits()[AMDGPU::FeatureWavefrontSize64]) return TokError("wavefront_size=6 requires +WavefrontSize64"); } } - if (ID == "enable_wgp_mode") { - if (G_00B848_WGP_MODE(Header.compute_pgm_resource_registers) && - !isGFX10Plus()) - return TokError("enable_wgp_mode=1 is only allowed on GFX10+"); - } - - if (ID == "enable_mem_ordered") { - if (G_00B848_MEM_ORDERED(Header.compute_pgm_resource_registers) && - !isGFX10Plus()) - return TokError("enable_mem_ordered=1 is only allowed on GFX10+"); - } - - if (ID == "enable_fwd_progress") { - if (G_00B848_FWD_PROGRESS(Header.compute_pgm_resource_registers) && - !isGFX10Plus()) - return TokError("enable_fwd_progress=1 is only allowed on GFX10+"); - } - return false; } bool AMDGPUAsmParser::ParseDirectiveAMDKernelCodeT() { - amd_kernel_code_t Header; - AMDGPU::initDefaultAMDKernelCodeT(Header, &getSTI()); + AMDGPUMCKernelCodeT KernelCode; + KernelCode.initDefault(&getSTI(), getContext()); while (true) { // Lex EndOfStatement. This is in a while loop, because lexing a comment @@ -5951,11 +5921,12 @@ bool AMDGPUAsmParser::ParseDirectiveAMDKernelCodeT() { if (ID == ".end_amd_kernel_code_t") break; - if (ParseAMDKernelCodeTValue(ID, Header)) + if (ParseAMDKernelCodeTValue(ID, KernelCode)) return true; } - getTargetStreamer().EmitAMDKernelCodeT(Header); + KernelCode.validate(&getSTI(), getContext()); + getTargetStreamer().EmitAMDKernelCodeT(KernelCode); return false; } diff --git a/llvm/lib/Target/AMDGPU/MCTargetDesc/AMDGPUTargetStreamer.cpp b/llvm/lib/Target/AMDGPU/MCTargetDesc/AMDGPUTargetStreamer.cpp index 02fe7be06280..00e64e3419ba 100644 --- a/llvm/lib/Target/AMDGPU/MCTargetDesc/AMDGPUTargetStreamer.cpp +++ b/llvm/lib/Target/AMDGPU/MCTargetDesc/AMDGPUTargetStreamer.cpp @@ -13,7 +13,6 @@ #include "AMDGPUTargetStreamer.h" #include "AMDGPUMCKernelDescriptor.h" #include "AMDGPUPTNote.h" -#include "AMDKernelCodeT.h" #include "Utils/AMDGPUBaseInfo.h" #include "Utils/AMDKernelCodeTUtils.h" #include "llvm/BinaryFormat/AMDGPUMetadataVerifier.h" @@ -240,10 +239,9 @@ void AMDGPUTargetAsmStreamer::EmitDirectiveAMDHSACodeObjectVersion( OS << "\t.amdhsa_code_object_version " << COV << '\n'; } -void -AMDGPUTargetAsmStreamer::EmitAMDKernelCodeT(const amd_kernel_code_t &Header) { +void AMDGPUTargetAsmStreamer::EmitAMDKernelCodeT(AMDGPUMCKernelCodeT &Header) { OS << "\t.amd_kernel_code_t\n"; - dumpAmdKernelCode(&Header, OS, "\t\t"); + Header.EmitKernelCodeT(OS, getContext()); OS << "\t.end_amd_kernel_code_t\n"; } @@ -789,12 +787,10 @@ unsigned AMDGPUTargetELFStreamer::getEFlagsV6() { void AMDGPUTargetELFStreamer::EmitDirectiveAMDGCNTarget() {} -void -AMDGPUTargetELFStreamer::EmitAMDKernelCodeT(const amd_kernel_code_t &Header) { - +void AMDGPUTargetELFStreamer::EmitAMDKernelCodeT(AMDGPUMCKernelCodeT &Header) { MCStreamer &OS = getStreamer(); OS.pushSection(); - OS.emitBytes(StringRef((const char*)&Header, sizeof(Header))); + Header.EmitKernelCodeT(OS, getContext()); OS.popSection(); } diff --git a/llvm/lib/Target/AMDGPU/MCTargetDesc/AMDGPUTargetStreamer.h b/llvm/lib/Target/AMDGPU/MCTargetDesc/AMDGPUTargetStreamer.h index 706897a5dc1f..e5c90060cb5d 100644 --- a/llvm/lib/Target/AMDGPU/MCTargetDesc/AMDGPUTargetStreamer.h +++ b/llvm/lib/Target/AMDGPU/MCTargetDesc/AMDGPUTargetStreamer.h @@ -13,8 +13,6 @@ #include "Utils/AMDGPUPALMetadata.h" #include "llvm/MC/MCStreamer.h" -struct amd_kernel_code_t; - namespace llvm { class MCELFStreamer; @@ -23,6 +21,7 @@ class formatted_raw_ostream; namespace AMDGPU { +struct AMDGPUMCKernelCodeT; struct MCKernelDescriptor; namespace HSAMD { struct Metadata; @@ -54,7 +53,7 @@ public: CodeObjectVersion = COV; } - virtual void EmitAMDKernelCodeT(const amd_kernel_code_t &Header){}; + virtual void EmitAMDKernelCodeT(AMDGPU::AMDGPUMCKernelCodeT &Header) {}; virtual void EmitAMDGPUSymbolType(StringRef SymbolName, unsigned Type){}; @@ -130,7 +129,7 @@ public: void EmitDirectiveAMDHSACodeObjectVersion(unsigned COV) override; - void EmitAMDKernelCodeT(const amd_kernel_code_t &Header) override; + void EmitAMDKernelCodeT(AMDGPU::AMDGPUMCKernelCodeT &Header) override; void EmitAMDGPUSymbolType(StringRef SymbolName, unsigned Type) override; @@ -186,7 +185,7 @@ public: void EmitDirectiveAMDGCNTarget() override; - void EmitAMDKernelCodeT(const amd_kernel_code_t &Header) override; + void EmitAMDKernelCodeT(AMDGPU::AMDGPUMCKernelCodeT &Header) override; void EmitAMDGPUSymbolType(StringRef SymbolName, unsigned Type) override; diff --git a/llvm/lib/Target/AMDGPU/SIDefines.h b/llvm/lib/Target/AMDGPU/SIDefines.h index 6d0e0b3f4de2..1e9bfc77ab92 100644 --- a/llvm/lib/Target/AMDGPU/SIDefines.h +++ b/llvm/lib/Target/AMDGPU/SIDefines.h @@ -1111,7 +1111,7 @@ enum Type { TRAP = -2, WORKGROUP = -1 }; #define C_00B84C_LDS_SIZE 0xFF007FFF #define S_00B84C_EXCP_EN(x) (((x) & 0x7F) << 24) #define G_00B84C_EXCP_EN(x) (((x) >> 24) & 0x7F) -#define C_00B84C_EXCP_EN +#define C_00B84C_EXCP_EN 0x80FFFFFF #define R_0286CC_SPI_PS_INPUT_ENA 0x0286CC #define R_0286D0_SPI_PS_INPUT_ADDR 0x0286D0 diff --git a/llvm/lib/Target/AMDGPU/Utils/AMDGPUBaseInfo.cpp b/llvm/lib/Target/AMDGPU/Utils/AMDGPUBaseInfo.cpp index 2beaf903542b..4b34fb27632a 100644 --- a/llvm/lib/Target/AMDGPU/Utils/AMDGPUBaseInfo.cpp +++ b/llvm/lib/Target/AMDGPU/Utils/AMDGPUBaseInfo.cpp @@ -11,6 +11,7 @@ #include "AMDGPUAsmUtils.h" #include "AMDKernelCodeT.h" #include "MCTargetDesc/AMDGPUMCTargetDesc.h" +#include "Utils/AMDKernelCodeTUtils.h" #include "llvm/ADT/StringExtras.h" #include "llvm/BinaryFormat/ELF.h" #include "llvm/IR/Attributes.h" @@ -1218,39 +1219,37 @@ unsigned getAllocatedNumVGPRBlocks(const MCSubtargetInfo *STI, } } // end namespace IsaInfo -void initDefaultAMDKernelCodeT(amd_kernel_code_t &Header, +void initDefaultAMDKernelCodeT(AMDGPUMCKernelCodeT &KernelCode, const MCSubtargetInfo *STI) { IsaVersion Version = getIsaVersion(STI->getCPU()); - - memset(&Header, 0, sizeof(Header)); - - Header.amd_kernel_code_version_major = 1; - Header.amd_kernel_code_version_minor = 2; - Header.amd_machine_kind = 1; // AMD_MACHINE_KIND_AMDGPU - Header.amd_machine_version_major = Version.Major; - Header.amd_machine_version_minor = Version.Minor; - Header.amd_machine_version_stepping = Version.Stepping; - Header.kernel_code_entry_byte_offset = sizeof(Header); - Header.wavefront_size = 6; + KernelCode.amd_kernel_code_version_major = 1; + KernelCode.amd_kernel_code_version_minor = 2; + KernelCode.amd_machine_kind = 1; // AMD_MACHINE_KIND_AMDGPU + KernelCode.amd_machine_version_major = Version.Major; + KernelCode.amd_machine_version_minor = Version.Minor; + KernelCode.amd_machine_version_stepping = Version.Stepping; + KernelCode.kernel_code_entry_byte_offset = sizeof(amd_kernel_code_t); + if (STI->getFeatureBits().test(FeatureWavefrontSize32)) { + KernelCode.wavefront_size = 5; + KernelCode.code_properties |= AMD_CODE_PROPERTY_ENABLE_WAVEFRONT_SIZE32; + } else { + KernelCode.wavefront_size = 6; + } // If the code object does not support indirect functions, then the value must // be 0xffffffff. - Header.call_convention = -1; + KernelCode.call_convention = -1; // These alignment values are specified in powers of two, so alignment = // 2^n. The minimum alignment is 2^4 = 16. - Header.kernarg_segment_alignment = 4; - Header.group_segment_alignment = 4; - Header.private_segment_alignment = 4; + KernelCode.kernarg_segment_alignment = 4; + KernelCode.group_segment_alignment = 4; + KernelCode.private_segment_alignment = 4; if (Version.Major >= 10) { - if (STI->getFeatureBits().test(FeatureWavefrontSize32)) { - Header.wavefront_size = 5; - Header.code_properties |= AMD_CODE_PROPERTY_ENABLE_WAVEFRONT_SIZE32; - } - Header.compute_pgm_resource_registers |= - S_00B848_WGP_MODE(STI->getFeatureBits().test(FeatureCuMode) ? 0 : 1) | - S_00B848_MEM_ORDERED(1); + KernelCode.compute_pgm_resource_registers |= + S_00B848_WGP_MODE(STI->getFeatureBits().test(FeatureCuMode) ? 0 : 1) | + S_00B848_MEM_ORDERED(1); } } diff --git a/llvm/lib/Target/AMDGPU/Utils/AMDGPUBaseInfo.h b/llvm/lib/Target/AMDGPU/Utils/AMDGPUBaseInfo.h index fc4147df76e3..3cfc42a7d24d 100644 --- a/llvm/lib/Target/AMDGPU/Utils/AMDGPUBaseInfo.h +++ b/llvm/lib/Target/AMDGPU/Utils/AMDGPUBaseInfo.h @@ -37,6 +37,7 @@ class raw_ostream; namespace AMDGPU { +struct AMDGPUMCKernelCodeT; struct IsaVersion; /// Generic target versions emitted by this version of LLVM. @@ -860,7 +861,7 @@ unsigned mapWMMA2AddrTo3AddrOpcode(unsigned Opc); LLVM_READONLY unsigned mapWMMA3AddrTo2AddrOpcode(unsigned Opc); -void initDefaultAMDKernelCodeT(amd_kernel_code_t &Header, +void initDefaultAMDKernelCodeT(AMDGPUMCKernelCodeT &Header, const MCSubtargetInfo *STI); bool isGroupSegment(const GlobalValue *GV); diff --git a/llvm/lib/Target/AMDGPU/Utils/AMDKernelCodeTInfo.h b/llvm/lib/Target/AMDGPU/Utils/AMDKernelCodeTInfo.h index 95ad3f35d18f..75cb6cffbd51 100644 --- a/llvm/lib/Target/AMDGPU/Utils/AMDKernelCodeTInfo.h +++ b/llvm/lib/Target/AMDGPU/Utils/AMDKernelCodeTInfo.h @@ -12,34 +12,51 @@ // //===----------------------------------------------------------------------===// -#define QNAME(name) amd_kernel_code_t::name +#define QNAME(name) AMDGPUMCKernelCodeT::name #define FLD_T(name) decltype(QNAME(name)), &QNAME(name) -#define FIELD2(sname, aname, name) \ - RECORD(sname, aname, printField, parseField) +#ifndef PRINTFIELD +#define PRINTFIELD(sname, aname, name) printField +#endif -#define FIELD(name) FIELD2(name, name, name) +#ifndef FIELD2 +#define FIELD2(sname, aname, name) \ + RECORD(sname, aname, PRINTFIELD(sname, aname, name), parseField) +#endif +#ifndef FIELD +#define FIELD(name) FIELD2(name, name, name) +#endif +#ifndef PRINTCODEPROP #define PRINTCODEPROP(name) \ printBitField +#endif +#ifndef PARSECODEPROP #define PARSECODEPROP(name) \ parseBitField +#endif +#ifndef CODEPROP #define CODEPROP(name, shift) \ RECORD(name, name, PRINTCODEPROP(shift), PARSECODEPROP(shift)) +#endif // have to define these lambdas because of Set/GetMacro +#ifndef PRINTCOMP #define PRINTCOMP(GetMacro, Shift) \ [](StringRef Name, const amd_kernel_code_t &C, raw_ostream &OS) { \ printName(OS, Name) << \ (int)GetMacro(C.compute_pgm_resource_registers >> Shift); \ } +#endif + +#ifndef PARSECOMP #define PARSECOMP(SetMacro, Shift) \ [](amd_kernel_code_t &C, MCAsmParser &MCParser, raw_ostream &Err) { \ int64_t Value = 0; \ @@ -49,15 +66,22 @@ C.compute_pgm_resource_registers |= SetMacro(Value) << Shift; \ return true; \ } +#endif +#ifndef COMPPGM #define COMPPGM(name, aname, GetMacro, SetMacro, Shift) \ RECORD(name, aname, PRINTCOMP(GetMacro, Shift), PARSECOMP(SetMacro, Shift)) +#endif +#ifndef COMPPGM1 #define COMPPGM1(name, aname, AccMacro) \ COMPPGM(name, aname, G_00B848_##AccMacro, S_00B848_##AccMacro, 0) +#endif +#ifndef COMPPGM2 #define COMPPGM2(name, aname, AccMacro) \ COMPPGM(name, aname, G_00B84C_##AccMacro, S_00B84C_##AccMacro, 32) +#endif /////////////////////////////////////////////////////////////////////////////// // Begin of the table @@ -143,13 +167,14 @@ FIELD(runtime_loader_kernel_symbol) #undef QNAME #undef FLD_T +#undef PRINTFIELD #undef FIELD2 #undef FIELD #undef PRINTCODEPROP #undef PARSECODEPROP #undef CODEPROP #undef PRINTCOMP -#undef PAPSECOMP +#undef PARSECOMP #undef COMPPGM #undef COMPPGM1 #undef COMPPGM2 diff --git a/llvm/lib/Target/AMDGPU/Utils/AMDKernelCodeTUtils.cpp b/llvm/lib/Target/AMDGPU/Utils/AMDKernelCodeTUtils.cpp index 6bbc8c315718..eaee1a2a9739 100644 --- a/llvm/lib/Target/AMDGPU/Utils/AMDKernelCodeTUtils.cpp +++ b/llvm/lib/Target/AMDGPU/Utils/AMDKernelCodeTUtils.cpp @@ -6,44 +6,205 @@ // //===----------------------------------------------------------------------===// // -/// \file - utility functions to parse/print amd_kernel_code_t structure +/// \file - utility functions to parse/print AMDGPUMCKernelCodeT structure // //===----------------------------------------------------------------------===// #include "AMDKernelCodeTUtils.h" #include "AMDKernelCodeT.h" #include "SIDefines.h" -#include "llvm/ADT/ArrayRef.h" -#include "llvm/ADT/StringMap.h" +#include "Utils/AMDGPUBaseInfo.h" +#include "llvm/ADT/IndexedMap.h" #include "llvm/ADT/StringRef.h" +#include "llvm/MC/MCContext.h" +#include "llvm/MC/MCExpr.h" #include "llvm/MC/MCParser/MCAsmLexer.h" #include "llvm/MC/MCParser/MCAsmParser.h" +#include "llvm/MC/MCStreamer.h" +#include "llvm/Support/MathExtras.h" #include "llvm/Support/raw_ostream.h" using namespace llvm; +using namespace llvm::AMDGPU; -static ArrayRef get_amd_kernel_code_t_FldNames() { - static StringRef const Table[] = { - "", // not found placeholder +// Generates the following for AMDGPUMCKernelCodeT struct members: +// - HasMemberXXXXX class +// A check to see if AMDGPUMCKernelCodeT has a specific member so it can +// determine which of the original amd_kernel_code_t members are duplicated +// (if the names don't match, the table driven strategy won't work). +// - IsMCExprXXXXX class +// Check whether a AMDGPUMCKernelcodeT struct member is MCExpr-ified or not. +// - GetMemberXXXXX class +// A retrieval helper for said member (of type const MCExpr *&). Will return +// a `Phony` const MCExpr * initialized to nullptr to preserve reference +// returns. +#define GEN_HAS_MEMBER(member) \ + class HasMember##member { \ + private: \ + struct KnownWithMember { \ + int member; \ + }; \ + class AmbiguousDerived : public AMDGPUMCKernelCodeT, \ + public KnownWithMember {}; \ + template \ + static constexpr std::false_type Test(decltype(U::member) *); \ + template static constexpr std::true_type Test(...); \ + \ + public: \ + static constexpr bool RESULT = \ + std::is_same_v(nullptr)), \ + std::true_type>; \ + }; \ + class IsMCExpr##member { \ + template , \ + U> * = nullptr> \ + static constexpr std::true_type HasMCExprType(decltype(U::member) *); \ + template static constexpr std::false_type HasMCExprType(...); \ + \ + public: \ + static constexpr bool RESULT = \ + std::is_same_v(nullptr)), \ + std::true_type>; \ + }; \ + class GetMember##member { \ + public: \ + static const MCExpr *Phony; \ + template * = nullptr> \ + static const MCExpr *&Get(U &C) { \ + assert(IsMCExpr##member::RESULT && \ + "Trying to retrieve member that does not exist."); \ + return C.member; \ + } \ + template * = nullptr> \ + static const MCExpr *&Get(U &C) { \ + return Phony; \ + } \ + }; \ + const MCExpr *GetMember##member::Phony = nullptr; + +// Cannot generate class declarations using the table driver approach (see table +// in AMDKernelCodeTInfo.h). Luckily, if any are missing here or eventually +// added to the table, an error should occur when trying to retrieve the table +// in getMCExprIndexTable. +GEN_HAS_MEMBER(amd_code_version_major) +GEN_HAS_MEMBER(amd_code_version_minor) +GEN_HAS_MEMBER(amd_machine_kind) +GEN_HAS_MEMBER(amd_machine_version_major) +GEN_HAS_MEMBER(amd_machine_version_minor) +GEN_HAS_MEMBER(amd_machine_version_stepping) + +GEN_HAS_MEMBER(kernel_code_entry_byte_offset) +GEN_HAS_MEMBER(kernel_code_prefetch_byte_size) + +GEN_HAS_MEMBER(granulated_workitem_vgpr_count) +GEN_HAS_MEMBER(granulated_wavefront_sgpr_count) +GEN_HAS_MEMBER(priority) +GEN_HAS_MEMBER(float_mode) +GEN_HAS_MEMBER(priv) +GEN_HAS_MEMBER(enable_dx10_clamp) +GEN_HAS_MEMBER(debug_mode) +GEN_HAS_MEMBER(enable_ieee_mode) +GEN_HAS_MEMBER(enable_wgp_mode) +GEN_HAS_MEMBER(enable_mem_ordered) +GEN_HAS_MEMBER(enable_fwd_progress) + +GEN_HAS_MEMBER(enable_sgpr_private_segment_wave_byte_offset) +GEN_HAS_MEMBER(user_sgpr_count) +GEN_HAS_MEMBER(enable_trap_handler) +GEN_HAS_MEMBER(enable_sgpr_workgroup_id_x) +GEN_HAS_MEMBER(enable_sgpr_workgroup_id_y) +GEN_HAS_MEMBER(enable_sgpr_workgroup_id_z) +GEN_HAS_MEMBER(enable_sgpr_workgroup_info) +GEN_HAS_MEMBER(enable_vgpr_workitem_id) +GEN_HAS_MEMBER(enable_exception_msb) +GEN_HAS_MEMBER(granulated_lds_size) +GEN_HAS_MEMBER(enable_exception) + +GEN_HAS_MEMBER(enable_sgpr_private_segment_buffer) +GEN_HAS_MEMBER(enable_sgpr_dispatch_ptr) +GEN_HAS_MEMBER(enable_sgpr_queue_ptr) +GEN_HAS_MEMBER(enable_sgpr_kernarg_segment_ptr) +GEN_HAS_MEMBER(enable_sgpr_dispatch_id) +GEN_HAS_MEMBER(enable_sgpr_flat_scratch_init) +GEN_HAS_MEMBER(enable_sgpr_private_segment_size) +GEN_HAS_MEMBER(enable_sgpr_grid_workgroup_count_x) +GEN_HAS_MEMBER(enable_sgpr_grid_workgroup_count_y) +GEN_HAS_MEMBER(enable_sgpr_grid_workgroup_count_z) +GEN_HAS_MEMBER(enable_wavefront_size32) +GEN_HAS_MEMBER(enable_ordered_append_gds) +GEN_HAS_MEMBER(private_element_size) +GEN_HAS_MEMBER(is_ptr64) +GEN_HAS_MEMBER(is_dynamic_callstack) +GEN_HAS_MEMBER(is_debug_enabled) +GEN_HAS_MEMBER(is_xnack_enabled) + +GEN_HAS_MEMBER(workitem_private_segment_byte_size) +GEN_HAS_MEMBER(workgroup_group_segment_byte_size) +GEN_HAS_MEMBER(gds_segment_byte_size) +GEN_HAS_MEMBER(kernarg_segment_byte_size) +GEN_HAS_MEMBER(workgroup_fbarrier_count) +GEN_HAS_MEMBER(wavefront_sgpr_count) +GEN_HAS_MEMBER(workitem_vgpr_count) +GEN_HAS_MEMBER(reserved_vgpr_first) +GEN_HAS_MEMBER(reserved_vgpr_count) +GEN_HAS_MEMBER(reserved_sgpr_first) +GEN_HAS_MEMBER(reserved_sgpr_count) +GEN_HAS_MEMBER(debug_wavefront_private_segment_offset_sgpr) +GEN_HAS_MEMBER(debug_private_segment_buffer_sgpr) +GEN_HAS_MEMBER(kernarg_segment_alignment) +GEN_HAS_MEMBER(group_segment_alignment) +GEN_HAS_MEMBER(private_segment_alignment) +GEN_HAS_MEMBER(wavefront_size) +GEN_HAS_MEMBER(call_convention) +GEN_HAS_MEMBER(runtime_loader_kernel_symbol) + +static ArrayRef get_amd_kernel_code_t_FldNames() { + static constexpr StringLiteral const Table[] = { + "", // not found placeholder #define RECORD(name, altName, print, parse) #name -#include "AMDKernelCodeTInfo.h" +#include "Utils/AMDKernelCodeTInfo.h" #undef RECORD }; return ArrayRef(Table); } -static ArrayRef get_amd_kernel_code_t_FldAltNames() { - static StringRef const Table[] = { - "", // not found placeholder +static ArrayRef get_amd_kernel_code_t_FldAltNames() { + static constexpr StringLiteral const Table[] = { + "", // not found placeholder #define RECORD(name, altName, print, parse) #altName -#include "AMDKernelCodeTInfo.h" +#include "Utils/AMDKernelCodeTInfo.h" +#undef RECORD + }; + return ArrayRef(Table); +} + +static ArrayRef hasMCExprVersionTable() { + static bool const Table[] = { +#define RECORD(name, altName, print, parse) (IsMCExpr##name::RESULT) +#include "Utils/AMDKernelCodeTInfo.h" #undef RECORD }; return ArrayRef(Table); } -static StringMap createIndexMap(const ArrayRef &names, - const ArrayRef &altNames) { +using RetrieveFx = const MCExpr *&(*)(AMDGPUMCKernelCodeT &); + +static ArrayRef getMCExprIndexTable() { + static const RetrieveFx Table[] = { +#define RECORD(name, altName, print, parse) GetMember##name::Get +#include "Utils/AMDKernelCodeTInfo.h" +#undef RECORD + }; + return ArrayRef(Table); +} + +static StringMap createIndexMap(ArrayRef names, + ArrayRef altNames) { StringMap map; assert(names.size() == altNames.size()); for (unsigned i = 0; i < names.size(); ++i) { @@ -59,62 +220,111 @@ static int get_amd_kernel_code_t_FieldIndex(StringRef name) { return map.lookup(name) - 1; // returns -1 if not found } -static StringRef get_amd_kernel_code_t_FieldName(int index) { - return get_amd_kernel_code_t_FldNames()[index + 1]; -} +static constexpr std::pair getShiftMask(unsigned Value) { + unsigned Shift = 0; + unsigned Mask = 0; -// Field printing + Mask = ~Value; + for (; !(Mask & 1); Shift++, Mask >>= 1) { + } -static raw_ostream &printName(raw_ostream &OS, StringRef Name) { - return OS << Name << " = "; + return std::make_pair(Shift, Mask); } -template -static void printField(StringRef Name, const amd_kernel_code_t &C, - raw_ostream &OS) { - printName(OS, Name) << (int)(C.*ptr); +static const MCExpr *MaskShiftSet(const MCExpr *Val, uint32_t Mask, + uint32_t Shift, MCContext &Ctx) { + if (Mask) { + const MCExpr *MaskExpr = MCConstantExpr::create(Mask, Ctx); + Val = MCBinaryExpr::createAnd(Val, MaskExpr, Ctx); + } + if (Shift) { + const MCExpr *ShiftExpr = MCConstantExpr::create(Shift, Ctx); + Val = MCBinaryExpr::createShl(Val, ShiftExpr, Ctx); + } + return Val; } -template -static void printBitField(StringRef Name, const amd_kernel_code_t &c, - raw_ostream &OS) { +static const MCExpr *MaskShiftGet(const MCExpr *Val, uint32_t Mask, + uint32_t Shift, MCContext &Ctx) { + if (Shift) { + const MCExpr *ShiftExpr = MCConstantExpr::create(Shift, Ctx); + Val = MCBinaryExpr::createLShr(Val, ShiftExpr, Ctx); + } + if (Mask) { + const MCExpr *MaskExpr = MCConstantExpr::create(Mask, Ctx); + Val = MCBinaryExpr::createAnd(Val, MaskExpr, Ctx); + } + return Val; +} + +class PrintField { +public: + template , T> * = nullptr> + static void printField(StringRef Name, const AMDGPUMCKernelCodeT &C, + raw_ostream &OS, MCContext &Ctx) { + OS << Name << " = "; + const MCExpr *Value = C.*ptr; + int64_t Val; + if (Value->evaluateAsAbsolute(Val)) + OS << Val; + else + Value->print(OS, Ctx.getAsmInfo()); + } + + template , T> * = nullptr> + static void printField(StringRef Name, const AMDGPUMCKernelCodeT &C, + raw_ostream &OS, MCContext &) { + OS << Name << " = " << (int)(C.*ptr); + } +}; + +template +static void printBitField(StringRef Name, const AMDGPUMCKernelCodeT &C, + raw_ostream &OS, MCContext &) { const auto Mask = (static_cast(1) << width) - 1; - printName(OS, Name) << (int)((c.*ptr >> shift) & Mask); + OS << Name << " = " << (int)((C.*ptr >> shift) & Mask); } -using PrintFx = void(*)(StringRef, const amd_kernel_code_t &, raw_ostream &); +using PrintFx = void (*)(StringRef, const AMDGPUMCKernelCodeT &, raw_ostream &, + MCContext &); static ArrayRef getPrinterTable() { static const PrintFx Table[] = { +#define COMPPGM1(name, aname, AccMacro) \ + COMPPGM(name, aname, C_00B848_##AccMacro, S_00B848_##AccMacro, 0) +#define COMPPGM2(name, aname, AccMacro) \ + COMPPGM(name, aname, C_00B84C_##AccMacro, S_00B84C_##AccMacro, 32) +#define PRINTFIELD(sname, aname, name) PrintField::printField +#define PRINTCOMP(Complement, PGMType) \ + [](StringRef Name, const AMDGPUMCKernelCodeT &C, raw_ostream &OS, \ + MCContext &Ctx) { \ + OS << Name << " = "; \ + auto [Shift, Mask] = getShiftMask(Complement); \ + const MCExpr *Value; \ + if (PGMType == 0) { \ + Value = \ + MaskShiftGet(C.compute_pgm_resource1_registers, Mask, Shift, Ctx); \ + } else { \ + Value = \ + MaskShiftGet(C.compute_pgm_resource2_registers, Mask, Shift, Ctx); \ + } \ + int64_t Val; \ + if (Value->evaluateAsAbsolute(Val)) \ + OS << Val; \ + else \ + Value->print(OS, Ctx.getAsmInfo()); \ + } #define RECORD(name, altName, print, parse) print -#include "AMDKernelCodeTInfo.h" +#include "Utils/AMDKernelCodeTInfo.h" #undef RECORD }; return ArrayRef(Table); } -void llvm::printAmdKernelCodeField(const amd_kernel_code_t &C, - int FldIndex, - raw_ostream &OS) { - auto Printer = getPrinterTable()[FldIndex]; - if (Printer) - Printer(get_amd_kernel_code_t_FieldName(FldIndex), C, OS); -} - -void llvm::dumpAmdKernelCode(const amd_kernel_code_t *C, - raw_ostream &OS, - const char *tab) { - const int Size = getPrinterTable().size(); - for (int i = 0; i < Size; ++i) { - OS << tab; - printAmdKernelCodeField(*C, i, OS); - OS << '\n'; - } -} - -// Field parsing - -static bool expectAbsExpression(MCAsmParser &MCParser, int64_t &Value, raw_ostream& Err) { +static bool expectAbsExpression(MCAsmParser &MCParser, int64_t &Value, + raw_ostream &Err) { if (MCParser.getLexer().isNot(AsmToken::Equal)) { Err << "expected '='"; @@ -129,8 +339,8 @@ static bool expectAbsExpression(MCAsmParser &MCParser, int64_t &Value, raw_ostre return true; } -template -static bool parseField(amd_kernel_code_t &C, MCAsmParser &MCParser, +template +static bool parseField(AMDGPUMCKernelCodeT &C, MCAsmParser &MCParser, raw_ostream &Err) { int64_t Value = 0; if (!expectAbsExpression(MCParser, Value, Err)) @@ -139,39 +349,241 @@ static bool parseField(amd_kernel_code_t &C, MCAsmParser &MCParser, return true; } -template -static bool parseBitField(amd_kernel_code_t &C, MCAsmParser &MCParser, +template +static bool parseBitField(AMDGPUMCKernelCodeT &C, MCAsmParser &MCParser, raw_ostream &Err) { int64_t Value = 0; if (!expectAbsExpression(MCParser, Value, Err)) return false; - const uint64_t Mask = ((UINT64_C(1) << width) - 1) << shift; + const uint64_t Mask = ((UINT64_C(1) << width) - 1) << shift; C.*ptr &= (T)~Mask; C.*ptr |= (T)((Value << shift) & Mask); return true; } -using ParseFx = bool(*)(amd_kernel_code_t &, MCAsmParser &MCParser, - raw_ostream &Err); +static bool parseExpr(MCAsmParser &MCParser, const MCExpr *&Value, + raw_ostream &Err) { + if (MCParser.getLexer().isNot(AsmToken::Equal)) { + Err << "expected '='"; + return false; + } + MCParser.getLexer().Lex(); + + if (MCParser.parseExpression(Value)) { + Err << "Could not parse expression"; + return false; + } + return true; +} + +using ParseFx = bool (*)(AMDGPUMCKernelCodeT &, MCAsmParser &, raw_ostream &); static ArrayRef getParserTable() { static const ParseFx Table[] = { +#define COMPPGM1(name, aname, AccMacro) \ + COMPPGM(name, aname, G_00B848_##AccMacro, C_00B848_##AccMacro, 0) +#define COMPPGM2(name, aname, AccMacro) \ + COMPPGM(name, aname, G_00B84C_##AccMacro, C_00B84C_##AccMacro, 32) +#define PARSECOMP(Complement, PGMType) \ + [](AMDGPUMCKernelCodeT &C, MCAsmParser &MCParser, \ + raw_ostream &Err) -> bool { \ + MCContext &Ctx = MCParser.getContext(); \ + const MCExpr *Value; \ + if (!parseExpr(MCParser, Value, Err)) \ + return false; \ + auto [Shift, Mask] = getShiftMask(Complement); \ + Value = MaskShiftSet(Value, Mask, Shift, Ctx); \ + const MCExpr *Compl = MCConstantExpr::create(Complement, Ctx); \ + if (PGMType == 0) { \ + C.compute_pgm_resource1_registers = MCBinaryExpr::createAnd( \ + C.compute_pgm_resource1_registers, Compl, Ctx); \ + C.compute_pgm_resource1_registers = MCBinaryExpr::createOr( \ + C.compute_pgm_resource1_registers, Value, Ctx); \ + } else { \ + C.compute_pgm_resource2_registers = MCBinaryExpr::createAnd( \ + C.compute_pgm_resource2_registers, Compl, Ctx); \ + C.compute_pgm_resource2_registers = MCBinaryExpr::createOr( \ + C.compute_pgm_resource2_registers, Value, Ctx); \ + } \ + return true; \ + } #define RECORD(name, altName, print, parse) parse -#include "AMDKernelCodeTInfo.h" +#include "Utils/AMDKernelCodeTInfo.h" #undef RECORD }; return ArrayRef(Table); } -bool llvm::parseAmdKernelCodeField(StringRef ID, - MCAsmParser &MCParser, - amd_kernel_code_t &C, - raw_ostream &Err) { +static void printAmdKernelCodeField(const AMDGPUMCKernelCodeT &C, int FldIndex, + raw_ostream &OS, MCContext &Ctx) { + auto Printer = getPrinterTable()[FldIndex]; + if (Printer) + Printer(get_amd_kernel_code_t_FldNames()[FldIndex + 1], C, OS, Ctx); +} + +void AMDGPUMCKernelCodeT::initDefault(const MCSubtargetInfo *STI, + MCContext &Ctx, bool InitMCExpr) { + AMDGPUMCKernelCodeT(); + + AMDGPU::initDefaultAMDKernelCodeT(*this, STI); + + if (InitMCExpr) { + const MCExpr *ZeroExpr = MCConstantExpr::create(0, Ctx); + compute_pgm_resource1_registers = + MCConstantExpr::create(Lo_32(compute_pgm_resource_registers), Ctx); + compute_pgm_resource2_registers = + MCConstantExpr::create(Hi_32(compute_pgm_resource_registers), Ctx); + is_dynamic_callstack = ZeroExpr; + wavefront_sgpr_count = ZeroExpr; + workitem_vgpr_count = ZeroExpr; + workitem_private_segment_byte_size = ZeroExpr; + } +} + +void AMDGPUMCKernelCodeT::validate(const MCSubtargetInfo *STI, MCContext &Ctx) { + int64_t Value; + if (!compute_pgm_resource1_registers->evaluateAsAbsolute(Value)) + return; + + if (G_00B848_DX10_CLAMP(Value) && AMDGPU::isGFX12Plus(*STI)) { + Ctx.reportError({}, "enable_dx10_clamp=1 is not allowed on GFX12+"); + return; + } + + if (G_00B848_IEEE_MODE(Value) && AMDGPU::isGFX12Plus(*STI)) { + Ctx.reportError({}, "enable_ieee_mode=1 is not allowed on GFX12+"); + return; + } + + if (G_00B848_WGP_MODE(Value) && !AMDGPU::isGFX10Plus(*STI)) { + Ctx.reportError({}, "enable_wgp_mode=1 is only allowed on GFX10+"); + return; + } + + if (G_00B848_MEM_ORDERED(Value) && !AMDGPU::isGFX10Plus(*STI)) { + Ctx.reportError({}, "enable_mem_ordered=1 is only allowed on GFX10+"); + return; + } + + if (G_00B848_FWD_PROGRESS(Value) && !AMDGPU::isGFX10Plus(*STI)) { + Ctx.reportError({}, "enable_fwd_progress=1 is only allowed on GFX10+"); + return; + } +} + +const MCExpr *&AMDGPUMCKernelCodeT::getMCExprForIndex(int Index) { + static const auto IndexTable = getMCExprIndexTable(); + return IndexTable[Index](*this); +} + +bool AMDGPUMCKernelCodeT::ParseKernelCodeT(StringRef ID, MCAsmParser &MCParser, + raw_ostream &Err) { const int Idx = get_amd_kernel_code_t_FieldIndex(ID); if (Idx < 0) { Err << "unexpected amd_kernel_code_t field name " << ID; return false; } + + if (hasMCExprVersionTable()[Idx]) { + const MCExpr *Value; + if (!parseExpr(MCParser, Value, Err)) + return false; + getMCExprForIndex(Idx) = Value; + return true; + } auto Parser = getParserTable()[Idx]; - return Parser ? Parser(C, MCParser, Err) : false; + return Parser ? Parser(*this, MCParser, Err) : false; +} + +void AMDGPUMCKernelCodeT::EmitKernelCodeT(raw_ostream &OS, MCContext &Ctx) { + const int Size = hasMCExprVersionTable().size(); + for (int i = 0; i < Size; ++i) { + OS << "\t\t"; + if (hasMCExprVersionTable()[i]) { + OS << get_amd_kernel_code_t_FldNames()[i + 1] << " = "; + int64_t Val; + const MCExpr *Value = getMCExprForIndex(i); + if (Value->evaluateAsAbsolute(Val)) + OS << Val; + else + Value->print(OS, Ctx.getAsmInfo()); + } else { + printAmdKernelCodeField(*this, i, OS, Ctx); + } + OS << '\n'; + } +} + +void AMDGPUMCKernelCodeT::EmitKernelCodeT(MCStreamer &OS, MCContext &Ctx) { + OS.emitIntValue(amd_kernel_code_version_major, /*Size=*/4); + OS.emitIntValue(amd_kernel_code_version_minor, /*Size=*/4); + OS.emitIntValue(amd_machine_kind, /*Size=*/2); + OS.emitIntValue(amd_machine_version_major, /*Size=*/2); + OS.emitIntValue(amd_machine_version_minor, /*Size=*/2); + OS.emitIntValue(amd_machine_version_stepping, /*Size=*/2); + OS.emitIntValue(kernel_code_entry_byte_offset, /*Size=*/8); + OS.emitIntValue(kernel_code_prefetch_byte_offset, /*Size=*/8); + OS.emitIntValue(kernel_code_prefetch_byte_size, /*Size=*/8); + OS.emitIntValue(reserved0, /*Size=*/8); + + if (compute_pgm_resource1_registers != nullptr) + OS.emitValue(compute_pgm_resource1_registers, /*Size=*/4); + else + OS.emitIntValue(Lo_32(compute_pgm_resource_registers), + /*Size=*/4); + + if (compute_pgm_resource2_registers != nullptr) + OS.emitValue(compute_pgm_resource2_registers, /*Size=*/4); + else + OS.emitIntValue(Hi_32(compute_pgm_resource_registers), + /*Size=*/4); + + if (is_dynamic_callstack != nullptr) { + const MCExpr *CodeProps = MCConstantExpr::create(code_properties, Ctx); + CodeProps = MCBinaryExpr::createOr( + CodeProps, + MaskShiftSet(is_dynamic_callstack, + (1 << AMD_CODE_PROPERTY_IS_DYNAMIC_CALLSTACK_WIDTH) - 1, + AMD_CODE_PROPERTY_IS_DYNAMIC_CALLSTACK_SHIFT, Ctx), + Ctx); + OS.emitValue(CodeProps, /*Size=*/4); + } else + OS.emitIntValue(code_properties, /*Size=*/4); + + if (workitem_private_segment_byte_size != nullptr) + OS.emitValue(workitem_private_segment_byte_size, /*Size=*/4); + else + OS.emitIntValue(0, /*Size=*/4); + + OS.emitIntValue(workgroup_group_segment_byte_size, /*Size=*/4); + OS.emitIntValue(gds_segment_byte_size, /*Size=*/4); + OS.emitIntValue(kernarg_segment_byte_size, /*Size=*/8); + OS.emitIntValue(workgroup_fbarrier_count, /*Size=*/4); + + if (wavefront_sgpr_count != nullptr) + OS.emitValue(wavefront_sgpr_count, /*Size=*/2); + else + OS.emitIntValue(0, /*Size=*/2); + + if (workitem_vgpr_count != nullptr) + OS.emitValue(workitem_vgpr_count, /*Size=*/2); + else + OS.emitIntValue(0, /*Size=*/2); + + OS.emitIntValue(reserved_vgpr_first, /*Size=*/2); + OS.emitIntValue(reserved_vgpr_count, /*Size=*/2); + OS.emitIntValue(reserved_sgpr_first, /*Size=*/2); + OS.emitIntValue(reserved_sgpr_count, /*Size=*/2); + OS.emitIntValue(debug_wavefront_private_segment_offset_sgpr, + /*Size=*/2); + OS.emitIntValue(debug_private_segment_buffer_sgpr, /*Size=*/2); + OS.emitIntValue(kernarg_segment_alignment, /*Size=*/1); + OS.emitIntValue(group_segment_alignment, /*Size=*/1); + OS.emitIntValue(private_segment_alignment, /*Size=*/1); + OS.emitIntValue(wavefront_size, /*Size=*/1); + + OS.emitIntValue(call_convention, /*Size=*/4); + OS.emitBytes(StringRef((const char *)reserved3, /*Size=*/12)); + OS.emitIntValue(runtime_loader_kernel_symbol, /*Size=*/8); + OS.emitBytes(StringRef((const char *)control_directives, /*Size=*/16 * 8)); } diff --git a/llvm/lib/Target/AMDGPU/Utils/AMDKernelCodeTUtils.h b/llvm/lib/Target/AMDGPU/Utils/AMDKernelCodeTUtils.h index 41d0e0d745e5..6aeb98f1ce14 100644 --- a/llvm/lib/Target/AMDGPU/Utils/AMDKernelCodeTUtils.h +++ b/llvm/lib/Target/AMDGPU/Utils/AMDKernelCodeTUtils.h @@ -7,29 +7,84 @@ //===----------------------------------------------------------------------===// // /// \file AMDKernelCodeTUtils.h +/// MC layer struct for AMDGPUMCKernelCodeT, provides MCExpr functionality where +/// required. +/// // //===----------------------------------------------------------------------===// -#ifndef LLVM_LIB_TARGET_AMDGPU_UTILS_AMDKERNELCODETUTILS_H -#define LLVM_LIB_TARGET_AMDGPU_UTILS_AMDKERNELCODETUTILS_H +#ifndef LLVM_LIB_TARGET_AMDGPU_MCTARGETDESC_AMDGPUMCKERNELCODET_H +#define LLVM_LIB_TARGET_AMDGPU_MCTARGETDESC_AMDGPUMCKERNELCODET_H -struct amd_kernel_code_t; +#include "AMDKernelCodeT.h" +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/StringRef.h" namespace llvm { - class MCAsmParser; +class MCContext; +class MCExpr; +class MCStreamer; +class MCSubtargetInfo; class raw_ostream; -class StringRef; +namespace AMDGPU { + +struct AMDGPUMCKernelCodeT { + AMDGPUMCKernelCodeT() = default; + + // Names of most (if not all) members should match the ones used for table + // driven (array) generation in AMDKernelCodeTInfo.h. + uint32_t amd_kernel_code_version_major = 0; + uint32_t amd_kernel_code_version_minor = 0; + uint16_t amd_machine_kind = 0; + uint16_t amd_machine_version_major = 0; + uint16_t amd_machine_version_minor = 0; + uint16_t amd_machine_version_stepping = 0; + int64_t kernel_code_entry_byte_offset = 0; + int64_t kernel_code_prefetch_byte_offset = 0; + uint64_t kernel_code_prefetch_byte_size = 0; + uint64_t reserved0 = 0; + uint64_t compute_pgm_resource_registers = 0; + uint32_t code_properties = 0; + uint32_t workgroup_group_segment_byte_size = 0; + uint32_t gds_segment_byte_size = 0; + uint64_t kernarg_segment_byte_size = 0; + uint32_t workgroup_fbarrier_count = 0; + uint16_t reserved_vgpr_first = 0; + uint16_t reserved_vgpr_count = 0; + uint16_t reserved_sgpr_first = 0; + uint16_t reserved_sgpr_count = 0; + uint16_t debug_wavefront_private_segment_offset_sgpr = 0; + uint16_t debug_private_segment_buffer_sgpr = 0; + uint8_t kernarg_segment_alignment = 0; + uint8_t group_segment_alignment = 0; + uint8_t private_segment_alignment = 0; + uint8_t wavefront_size = 0; + int32_t call_convention = 0; + uint8_t reserved3[12] = {0}; + uint64_t runtime_loader_kernel_symbol = 0; + uint64_t control_directives[16] = {0}; + + const MCExpr *compute_pgm_resource1_registers = nullptr; + const MCExpr *compute_pgm_resource2_registers = nullptr; + + const MCExpr *is_dynamic_callstack = nullptr; + const MCExpr *wavefront_sgpr_count = nullptr; + const MCExpr *workitem_vgpr_count = nullptr; + const MCExpr *workitem_private_segment_byte_size = nullptr; -void printAmdKernelCodeField(const amd_kernel_code_t &C, int FldIndex, - raw_ostream &OS); + void initDefault(const MCSubtargetInfo *STI, MCContext &Ctx, + bool InitMCExpr = true); + void validate(const MCSubtargetInfo *STI, MCContext &Ctx); -void dumpAmdKernelCode(const amd_kernel_code_t *C, raw_ostream &OS, - const char *tab); + const MCExpr *&getMCExprForIndex(int Index); -bool parseAmdKernelCodeField(StringRef ID, MCAsmParser &Parser, - amd_kernel_code_t &C, raw_ostream &Err); + bool ParseKernelCodeT(StringRef ID, MCAsmParser &MCParser, raw_ostream &Err); + void EmitKernelCodeT(raw_ostream &OS, MCContext &Ctx); + void EmitKernelCodeT(MCStreamer &OS, MCContext &Ctx); +}; +} // end namespace AMDGPU } // end namespace llvm -#endif // LLVM_LIB_TARGET_AMDGPU_UTILS_AMDKERNELCODETUTILS_H +#endif // LLVM_LIB_TARGET_AMDGPU_MCTARGETDESC_AMDGPUMCKERNELCODET_H diff --git a/llvm/lib/Target/AMDGPU/Utils/CMakeLists.txt b/llvm/lib/Target/AMDGPU/Utils/CMakeLists.txt index 19d3b690b131..2f4ce8eaf1d6 100644 --- a/llvm/lib/Target/AMDGPU/Utils/CMakeLists.txt +++ b/llvm/lib/Target/AMDGPU/Utils/CMakeLists.txt @@ -11,6 +11,7 @@ add_llvm_component_library(LLVMAMDGPUUtils CodeGenTypes Core MC + MCParser Support TargetParser diff --git a/llvm/test/CodeGen/AMDGPU/kernel_code_t_recurse.ll b/llvm/test/CodeGen/AMDGPU/kernel_code_t_recurse.ll new file mode 100644 index 000000000000..cdd6e88dd103 --- /dev/null +++ b/llvm/test/CodeGen/AMDGPU/kernel_code_t_recurse.ll @@ -0,0 +1,24 @@ +; RUN: llc -mtriple=amdgcn-mesa-mesa3d < %s | FileCheck %s + +; CHECK-LABEL: non_kernel_recursion: +define void @non_kernel_recursion(i32 %val) #2 { + %cmp = icmp eq i32 %val, 0 + br i1 %cmp, label %ret, label %call + +call: + %val.sub1 = sub i32 %val, 1 + call void @non_kernel_recursion(i32 %val.sub1) + br label %ret + +ret: + ret void +} + +; CHECK-LABEL: kernel_caller_recursion: +; CHECK: .amd_kernel_code_t +; CHECK: is_dynamic_callstack = 1 +; CHECK: .end_amd_kernel_code_t +define amdgpu_kernel void @kernel_caller_recursion(i32 %n) #0 { + call void @non_kernel_recursion(i32 %n) + ret void +} diff --git a/llvm/test/MC/AMDGPU/amd_kernel_code_t.s b/llvm/test/MC/AMDGPU/amd_kernel_code_t.s new file mode 100644 index 000000000000..052ec0bfabb8 --- /dev/null +++ b/llvm/test/MC/AMDGPU/amd_kernel_code_t.s @@ -0,0 +1,171 @@ +; RUN: llvm-mc -triple=amdgcn-mesa-mesa3d -mcpu=gfx900 -filetype=asm < %s | FileCheck --check-prefix=ASM %s +; RUN: llvm-mc -triple=amdgcn-mesa-mesa3d -mcpu=gfx900 -filetype=obj < %s > %t +; RUN: llvm-objdump -s %t | FileCheck --check-prefix=OBJDUMP %s + +; OBJDUMP: Contents of section .known_is_dynamic_callstack: +; OBJDUMP: 0030 00000000 00000000 00001000 00000000 + +; OBJDUMP: Contents of section .known_wavefront_sgpr_count: +; OBJDUMP: 0050 00000000 01000000 00000000 00000000 + +; OBJDUMP: Contents of section .known_workitem_vgpr_count: +; OBJDUMP: 0050 00000000 00000100 00000000 00000000 + +; OBJDUMP: Contents of section .known_workitem_private_segment_byte_size: +; OBJDUMP: 0030 00000000 00000000 00000000 01000000 + +; OBJDUMP: Contents of section .known_granulated_workitem_vgpr_count: +; OBJDUMP: 0030 01000000 00000000 00000000 00000000 + +; OBJDUMP: Contents of section .known_enable_sgpr_workgroup_id_x: +; OBJDUMP: 0030 00000000 80000000 00000000 00000000 + +; OBJDUMP: Contents of section .unknown_is_dynamic_callstack: +; OBJDUMP: 0030 00000000 00000000 00001000 00000000 + +; OBJDUMP: Contents of section .unknown_wavefront_sgpr_count: +; OBJDUMP: 0050 00000000 01000000 00000000 00000000 + +; OBJDUMP: Contents of section .unknown_workitem_vgpr_count: +; OBJDUMP: 0050 00000000 00000100 00000000 00000000 + +; OBJDUMP: Contents of section .unknown_workitem_private_segment_byte_size: +; OBJDUMP: 0030 00000000 00000000 00000000 01000000 + +; OBJDUMP: Contents of section .unknown_granulated_workitem_vgpr_count: +; OBJDUMP: 0030 01000000 00000000 00000000 00000000 + +; OBJDUMP: Contents of section .unknown_enable_sgpr_workgroup_id_x: +; OBJDUMP: 0030 00000000 80000000 00000000 00000000 + +.set known, 1 + +; ASM-LABEL: known_is_dynamic_callstack: +; ASM: is_dynamic_callstack = 1 +.section .known_is_dynamic_callstack +known_is_dynamic_callstack: + .amd_kernel_code_t + is_dynamic_callstack = known + .end_amd_kernel_code_t + s_endpgm + +; ASM-LABEL: known_wavefront_sgpr_count: +; ASM: wavefront_sgpr_count = 1 +.section .known_wavefront_sgpr_count +known_wavefront_sgpr_count: + .amd_kernel_code_t + wavefront_sgpr_count = known + .end_amd_kernel_code_t + s_endpgm + +; ASM-LABEL: known_workitem_vgpr_count: +; ASM: workitem_vgpr_count = 1 +.section .known_workitem_vgpr_count +known_workitem_vgpr_count: + .amd_kernel_code_t + workitem_vgpr_count = known + .end_amd_kernel_code_t + s_endpgm + +; ASM-LABEL: known_workitem_private_segment_byte_size: +; ASM: workitem_private_segment_byte_size = 1 +.section .known_workitem_private_segment_byte_size +known_workitem_private_segment_byte_size: + .amd_kernel_code_t + workitem_private_segment_byte_size = known + .end_amd_kernel_code_t + s_endpgm + +; ASM-LABEL: known_granulated_workitem_vgpr_count: +; ASM: granulated_workitem_vgpr_count = 1 +.section .known_granulated_workitem_vgpr_count +known_granulated_workitem_vgpr_count: + .amd_kernel_code_t + granulated_workitem_vgpr_count = known + .end_amd_kernel_code_t + s_endpgm + +; ASM-LABEL: known_enable_sgpr_workgroup_id_x: +; ASM: enable_sgpr_workgroup_id_x = 1 +.section .known_enable_sgpr_workgroup_id_x +known_enable_sgpr_workgroup_id_x: + .amd_kernel_code_t + enable_sgpr_workgroup_id_x = known + .end_amd_kernel_code_t + s_endpgm + +; ASM-LABEL: unknown_is_dynamic_callstack: +; ASM: is_dynamic_callstack = unknown +.section .unknown_is_dynamic_callstack +unknown_is_dynamic_callstack: + .amd_kernel_code_t + is_dynamic_callstack = unknown + .end_amd_kernel_code_t + s_endpgm + +; ASM-LABEL: unknown_wavefront_sgpr_count: +; ASM: wavefront_sgpr_count = unknown +.section .unknown_wavefront_sgpr_count +unknown_wavefront_sgpr_count: + .amd_kernel_code_t + wavefront_sgpr_count = unknown + .end_amd_kernel_code_t + s_endpgm + +; ASM-LABEL: unknown_workitem_vgpr_count: +; ASM: workitem_vgpr_count = unknown +.section .unknown_workitem_vgpr_count +unknown_workitem_vgpr_count: + .amd_kernel_code_t + workitem_vgpr_count = unknown + .end_amd_kernel_code_t + s_endpgm + +; ASM-LABEL: unknown_workitem_private_segment_byte_size: +; ASM: workitem_private_segment_byte_size = unknown +.section .unknown_workitem_private_segment_byte_size +unknown_workitem_private_segment_byte_size: + .amd_kernel_code_t + workitem_private_segment_byte_size = unknown + .end_amd_kernel_code_t + s_endpgm + +; ASM-LABEL: unknown_granulated_workitem_vgpr_count: +; ASM: granulated_workitem_vgpr_count = ((0&4294967232)|(unknown&63))&63 +; ASM: granulated_wavefront_sgpr_count = (((0&4294967232)|(unknown&63))>>6)&15 +; ASM: priority = (((0&4294967232)|(unknown&63))>>10)&3 +; ASM: float_mode = (((0&4294967232)|(unknown&63))>>12)&255 +; ASM: priv = (((0&4294967232)|(unknown&63))>>20)&1 +; ASM: enable_dx10_clamp = (((0&4294967232)|(unknown&63))>>21)&1 +; ASM: debug_mode = (((0&4294967232)|(unknown&63))>>22)&1 +; ASM: enable_ieee_mode = (((0&4294967232)|(unknown&63))>>23)&1 +; ASM: enable_wgp_mode = (((0&4294967232)|(unknown&63))>>29)&1 +; ASM: enable_mem_ordered = (((0&4294967232)|(unknown&63))>>30)&1 +; ASM: enable_fwd_progress = (((0&4294967232)|(unknown&63))>>31)&1 +.section .unknown_granulated_workitem_vgpr_count +unknown_granulated_workitem_vgpr_count: + .amd_kernel_code_t + granulated_workitem_vgpr_count = unknown + .end_amd_kernel_code_t + s_endpgm + +; ASM-LABEL: unknown_enable_sgpr_workgroup_id_x: +; ASM: enable_sgpr_private_segment_wave_byte_offset = ((0&4294967167)|((unknown&1)<<7))&1 +; ASM: user_sgpr_count = (((0&4294967167)|((unknown&1)<<7))>>1)&31 +; ASM: enable_trap_handler = (((0&4294967167)|((unknown&1)<<7))>>6)&1 +; ASM: enable_sgpr_workgroup_id_x = (((0&4294967167)|((unknown&1)<<7))>>7)&1 +; ASM: enable_sgpr_workgroup_id_y = (((0&4294967167)|((unknown&1)<<7))>>8)&1 +; ASM: enable_sgpr_workgroup_id_z = (((0&4294967167)|((unknown&1)<<7))>>9)&1 +; ASM: enable_sgpr_workgroup_info = (((0&4294967167)|((unknown&1)<<7))>>10)&1 +; ASM: enable_vgpr_workitem_id = (((0&4294967167)|((unknown&1)<<7))>>11)&3 +; ASM: enable_exception_msb = (((0&4294967167)|((unknown&1)<<7))>>13)&3 +; ASM: granulated_lds_size = (((0&4294967167)|((unknown&1)<<7))>>15)&511 +; ASM: enable_exception = (((0&4294967167)|((unknown&1)<<7))>>24)&127 +.section .unknown_enable_sgpr_workgroup_id_x +unknown_enable_sgpr_workgroup_id_x: + .amd_kernel_code_t + enable_sgpr_workgroup_id_x = unknown + .end_amd_kernel_code_t + s_endpgm + +.set unknown, 1 -- GitLab From 527276832f7e8f109dbab8eb3b01631f68cfe50e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Don=C3=A1t=20Nagy?= Date: Wed, 22 May 2024 15:04:22 +0200 Subject: [PATCH 119/452] [clang-tidy][NFCI] Simplify bugprone-sizeof-expression (#93024) This commit eliminates a redundant matcher subexpression from the implementation of the "sizeof-pointer-to-aggregate" part of the clang-tidy check `bugprone-sizeof-expression`. I'm fairly certain that anything that was previously matched by the deleted matcher `StructAddrOfExpr` is also covered by the more general `PointerToStructExpr` (which remains in the same `anyOf`). This commit is made to "prepare the ground" for a followup change that would merge the functionality of the Clang Static Analyzer checker `alpha.core.SizeofPtr` into this clang-tidy check. --- .../bugprone/SizeofExpressionCheck.cpp | 32 +++++++++---------- 1 file changed, 15 insertions(+), 17 deletions(-) diff --git a/clang-tools-extra/clang-tidy/bugprone/SizeofExpressionCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/SizeofExpressionCheck.cpp index a1cffbc66619..5e64d23874ec 100644 --- a/clang-tools-extra/clang-tidy/bugprone/SizeofExpressionCheck.cpp +++ b/clang-tools-extra/clang-tidy/bugprone/SizeofExpressionCheck.cpp @@ -144,16 +144,13 @@ void SizeofExpressionCheck::registerMatchers(MatchFinder *Finder) { unaryOperator(hasUnaryOperand(ArrayExpr), unless(hasOperatorName("*"))), binaryOperator(hasEitherOperand(ArrayExpr)), castExpr(hasSourceExpression(ArrayExpr)))); - const auto PointerToArrayExpr = ignoringParenImpCasts( - hasType(hasCanonicalType(pointerType(pointee(arrayType()))))); + const auto PointerToArrayExpr = + hasType(hasCanonicalType(pointerType(pointee(arrayType())))); - const auto StructAddrOfExpr = unaryOperator( - hasOperatorName("&"), hasUnaryOperand(ignoringParenImpCasts( - hasType(hasCanonicalType(recordType()))))); const auto PointerToStructType = hasUnqualifiedDesugaredType(pointerType(pointee(recordType()))); - const auto PointerToStructExpr = ignoringParenImpCasts(expr( - hasType(hasCanonicalType(PointerToStructType)), unless(cxxThisExpr()))); + const auto PointerToStructExpr = expr( + hasType(hasCanonicalType(PointerToStructType)), unless(cxxThisExpr())); const auto ArrayOfPointersExpr = ignoringParenImpCasts( hasType(hasCanonicalType(arrayType(hasElementType(pointerType())) @@ -166,18 +163,19 @@ void SizeofExpressionCheck::registerMatchers(MatchFinder *Finder) { ignoringParenImpCasts(arraySubscriptExpr( hasBase(ArrayOfSamePointersExpr), hasIndex(ZeroLiteral))); const auto ArrayLengthExprDenom = - expr(hasParent(expr(ignoringParenImpCasts(binaryOperator( - hasOperatorName("/"), hasLHS(ignoringParenImpCasts(sizeOfExpr( - has(ArrayOfPointersExpr)))))))), + expr(hasParent(binaryOperator(hasOperatorName("/"), + hasLHS(ignoringParenImpCasts(sizeOfExpr( + has(ArrayOfPointersExpr)))))), sizeOfExpr(has(ArrayOfSamePointersZeroSubscriptExpr))); - Finder->addMatcher(expr(anyOf(sizeOfExpr(has(ignoringParenImpCasts(anyOf( - ArrayCastExpr, PointerToArrayExpr, - StructAddrOfExpr, PointerToStructExpr)))), - sizeOfExpr(has(PointerToStructType))), - unless(ArrayLengthExprDenom)) - .bind("sizeof-pointer-to-aggregate"), - this); + Finder->addMatcher( + expr(sizeOfExpr(anyOf( + has(ignoringParenImpCasts(anyOf( + ArrayCastExpr, PointerToArrayExpr, PointerToStructExpr))), + has(PointerToStructType))), + unless(ArrayLengthExprDenom)) + .bind("sizeof-pointer-to-aggregate"), + this); } // Detect expression like: sizeof(expr) <= k for a suspicious constant 'k'. -- GitLab From b99b6b78f0c611fa1241dfcc7cdd8970f8b6369c Mon Sep 17 00:00:00 2001 From: Tom Eccles Date: Wed, 22 May 2024 14:29:30 +0100 Subject: [PATCH 120/452] [flang][Driver][test] add missing run lines to fopenmp test (#92784) I believe these were forgotten when copying the clang in #86816. This was flagged because the CHECK lines for CHECK-LD-ANY* had no associated RUN line. See https://github.com/llvm/llvm-project/pull/92387#issuecomment-2119170354 --- flang/test/Driver/fopenmp.f90 | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/flang/test/Driver/fopenmp.f90 b/flang/test/Driver/fopenmp.f90 index c71d34dc9e7e..2fdd69425eca 100644 --- a/flang/test/Driver/fopenmp.f90 +++ b/flang/test/Driver/fopenmp.f90 @@ -51,9 +51,14 @@ ! We'd like to check that the default is sane, but until we have the ability ! to *always* semantically analyze OpenMP without always generating runtime ! calls (in the event of an unsupported runtime), we don't have a good way to -! test the CC1 invocation. Instead, just ensure we do eventually link *some* +! test the FC1 invocation. Instead, just ensure we do eventually link *some* ! OpenMP runtime. ! +! RUN: %flang -target x86_64-linux-gnu -fopenmp %s -o %t -### 2>&1 | FileCheck %s --check-prefix=CHECK-LD-ANY +! RUN: %flang -target x86_64-darwin -fopenmp %s -o %t -### 2>&1 | FileCheck %s --check-prefix=CHECK-LD-ANY +! RUN: %flang -target x86_64-freebsd -fopenmp %s -o %t -### 2>&1 | FileCheck %s --check-prefix=CHECK-LD-ANY +! RUN: %flang -target x86_64-windows-gnu -fopenmp %s -o %t -### 2>&1 | FileCheck %s --check-prefix=CHECK-LD-ANYMD +! ! CHECK-LD-ANY: "{{.*}}ld{{(.exe)?}}" ! CHECK-LD-ANY: "-l{{(omp|gomp|iomp5)}}" ! -- GitLab From f78febf7a87832fb2078961a6d8881b527c917bb Mon Sep 17 00:00:00 2001 From: Simon Pilgrim Date: Wed, 22 May 2024 14:29:49 +0100 Subject: [PATCH 121/452] [DAG] ComputeNumSignBits - add AVGCEILS/AVGFLOORS handling (#93021) Pulled from #92096 --- .../lib/CodeGen/SelectionDAG/SelectionDAG.cpp | 7 ++ llvm/test/CodeGen/AArch64/hadd-combine.ll | 67 ++++++++++++++++++- 2 files changed, 73 insertions(+), 1 deletion(-) diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp index 777bbf071732..b05649c6ce95 100644 --- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp @@ -4780,6 +4780,13 @@ unsigned SelectionDAG::ComputeNumSignBits(SDValue Op, const APInt &DemandedElts, (VTBits - SignBitsOp0 + 1) + (VTBits - SignBitsOp1 + 1); return OutValidBits > VTBits ? 1 : VTBits - OutValidBits + 1; } + case ISD::AVGCEILS: + case ISD::AVGFLOORS: + Tmp = ComputeNumSignBits(Op.getOperand(0), DemandedElts, Depth + 1); + if (Tmp == 1) + return 1; // Early out. + Tmp2 = ComputeNumSignBits(Op.getOperand(1), DemandedElts, Depth + 1); + return std::min(Tmp, Tmp2); case ISD::SREM: // The sign bit is the LHS's sign bit, except when the result of the // remainder is zero. The magnitude of the result should be less than or diff --git a/llvm/test/CodeGen/AArch64/hadd-combine.ll b/llvm/test/CodeGen/AArch64/hadd-combine.ll index c0f76784eb37..28f454767c12 100644 --- a/llvm/test/CodeGen/AArch64/hadd-combine.ll +++ b/llvm/test/CodeGen/AArch64/hadd-combine.ll @@ -955,6 +955,71 @@ define <8 x i16> @urhadd_demandedelts(<8 x i16> %a0, <8 x i16> %a1) { ret <8 x i16> %r0 } +; Remove unnecessary sign_extend_inreg after shadd +define <2 x i32> @shadd_signbits_v2i32(<2 x i32> %a0, <2 x i32> %a1, ptr %p2) { +; CHECK-LABEL: shadd_signbits_v2i32: +; CHECK: // %bb.0: +; CHECK-NEXT: sshr v0.2s, v0.2s, #17 +; CHECK-NEXT: sshr v1.2s, v1.2s, #17 +; CHECK-NEXT: shadd v0.2s, v0.2s, v1.2s +; CHECK-NEXT: str d0, [x0] +; CHECK-NEXT: ret + %x0 = ashr <2 x i32> %a0, + %x1 = ashr <2 x i32> %a1, + %m = and <2 x i32> %x0, %x1 + %s = xor <2 x i32> %x0, %x1 + %x = ashr <2 x i32> %s, + %avg = add <2 x i32> %m, %x + %avg1 = shl <2 x i32> %avg, + %avg2 = ashr <2 x i32> %avg1, + store <2 x i32> %avg, ptr %p2 ; extra use + ret <2 x i32> %avg2 +} + +; Remove unnecessary sign_extend_inreg after srhadd +define <2 x i32> @srhadd_signbits_v2i32(<2 x i32> %a0, <2 x i32> %a1, ptr %p2) { +; CHECK-LABEL: srhadd_signbits_v2i32: +; CHECK: // %bb.0: +; CHECK-NEXT: sshr v0.2s, v0.2s, #17 +; CHECK-NEXT: sshr v1.2s, v1.2s, #17 +; CHECK-NEXT: srhadd v0.2s, v0.2s, v1.2s +; CHECK-NEXT: str d0, [x0] +; CHECK-NEXT: ret + %x0 = ashr <2 x i32> %a0, + %x1 = ashr <2 x i32> %a1, + %m = or <2 x i32> %x0, %x1 + %s = xor <2 x i32> %x0, %x1 + %x = ashr <2 x i32> %s, + %avg = sub <2 x i32> %m, %x + %avg1 = shl <2 x i32> %avg, + %avg2 = ashr <2 x i32> %avg1, + store <2 x i32> %avg, ptr %p2 ; extra use + ret <2 x i32> %avg2 +} + +; negative test - not enough signbits to remove sign_extend_inreg after srhadd +define <2 x i32> @srhadd_signbits_v2i32_negative(<2 x i32> %a0, <2 x i32> %a1, ptr %p2) { +; CHECK-LABEL: srhadd_signbits_v2i32_negative: +; CHECK: // %bb.0: +; CHECK-NEXT: sshr v0.2s, v0.2s, #17 +; CHECK-NEXT: sshr v1.2s, v1.2s, #17 +; CHECK-NEXT: srhadd v1.2s, v0.2s, v1.2s +; CHECK-NEXT: shl v0.2s, v1.2s, #22 +; CHECK-NEXT: str d1, [x0] +; CHECK-NEXT: sshr v0.2s, v0.2s, #22 +; CHECK-NEXT: ret + %x0 = ashr <2 x i32> %a0, + %x1 = ashr <2 x i32> %a1, + %m = or <2 x i32> %x0, %x1 + %s = xor <2 x i32> %x0, %x1 + %x = ashr <2 x i32> %s, + %avg = sub <2 x i32> %m, %x + %avg1 = shl <2 x i32> %avg, + %avg2 = ashr <2 x i32> %avg1, + store <2 x i32> %avg, ptr %p2 ; extra use + ret <2 x i32> %avg2 +} + declare <8 x i8> @llvm.aarch64.neon.shadd.v8i8(<8 x i8>, <8 x i8>) declare <4 x i16> @llvm.aarch64.neon.shadd.v4i16(<4 x i16>, <4 x i16>) declare <2 x i32> @llvm.aarch64.neon.shadd.v2i32(<2 x i32>, <2 x i32>) @@ -979,4 +1044,4 @@ declare <8 x i16> @llvm.aarch64.neon.srhadd.v8i16(<8 x i16>, <8 x i16>) declare <4 x i32> @llvm.aarch64.neon.srhadd.v4i32(<4 x i32>, <4 x i32>) declare <16 x i8> @llvm.aarch64.neon.urhadd.v16i8(<16 x i8>, <16 x i8>) declare <8 x i16> @llvm.aarch64.neon.urhadd.v8i16(<8 x i16>, <8 x i16>) -declare <4 x i32> @llvm.aarch64.neon.urhadd.v4i32(<4 x i32>, <4 x i32>) \ No newline at end of file +declare <4 x i32> @llvm.aarch64.neon.urhadd.v4i32(<4 x i32>, <4 x i32>) -- GitLab From e3bd627f53b6c7e1c16368803c3f119910cc5c84 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timm=20B=C3=A4der?= Date: Wed, 22 May 2024 13:11:47 +0200 Subject: [PATCH 122/452] [clang][Interp][NFC] Retrieve active union field in Pointer::toRValue() --- clang/lib/AST/Interp/Pointer.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/clang/lib/AST/Interp/Pointer.cpp b/clang/lib/AST/Interp/Pointer.cpp index e45c291668ca..252f7ea46086 100644 --- a/clang/lib/AST/Interp/Pointer.cpp +++ b/clang/lib/AST/Interp/Pointer.cpp @@ -351,6 +351,7 @@ std::optional Pointer::toRValue(const Context &Ctx) const { } else { Ok &= Composite(FieldTy, FP, Value); } + ActiveField = FP.getFieldDesc()->asFieldDecl(); break; } } -- GitLab From 7d9634e527fe52bf20a9036be6e5771f8fc4de17 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timm=20B=C3=A4der?= Date: Wed, 22 May 2024 14:01:54 +0200 Subject: [PATCH 123/452] [clang][Interp][NFC] Propagate IsActive state in unions properly This resolves an older FIXME comment. --- clang/lib/AST/Interp/Descriptor.cpp | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/clang/lib/AST/Interp/Descriptor.cpp b/clang/lib/AST/Interp/Descriptor.cpp index d0466902247b..746b765ca421 100644 --- a/clang/lib/AST/Interp/Descriptor.cpp +++ b/clang/lib/AST/Interp/Descriptor.cpp @@ -137,9 +137,8 @@ static void moveArrayDesc(Block *B, const std::byte *Src, std::byte *Dst, } static void initField(Block *B, std::byte *Ptr, bool IsConst, bool IsMutable, - bool IsActive, const Descriptor *D, + bool IsActive, bool IsUnion, const Descriptor *D, unsigned FieldOffset) { - bool IsUnion = false; // FIXME auto *Desc = reinterpret_cast(Ptr + FieldOffset) - 1; Desc->Offset = FieldOffset; Desc->Desc = D; @@ -174,7 +173,7 @@ static void initBase(Block *B, std::byte *Ptr, bool IsConst, bool IsMutable, initBase(B, Ptr + FieldOffset, IsConst, IsMutable, IsActive, V.Desc, V.Offset, false); for (const auto &F : D->ElemRecord->fields()) - initField(B, Ptr + FieldOffset, IsConst, IsMutable, IsActive, F.Desc, + initField(B, Ptr + FieldOffset, IsConst, IsMutable, IsActive, IsUnion, F.Desc, F.Offset); // If this is initializing a virtual base, we do NOT want to consider its @@ -193,7 +192,7 @@ static void ctorRecord(Block *B, std::byte *Ptr, bool IsConst, bool IsMutable, for (const auto &V : D->ElemRecord->bases()) initBase(B, Ptr, IsConst, IsMutable, IsActive, V.Desc, V.Offset, false); for (const auto &F : D->ElemRecord->fields()) - initField(B, Ptr, IsConst, IsMutable, IsActive, F.Desc, F.Offset); + initField(B, Ptr, IsConst, IsMutable, IsActive, D->ElemRecord->isUnion(), F.Desc, F.Offset); for (const auto &V : D->ElemRecord->virtual_bases()) initBase(B, Ptr, IsConst, IsMutable, IsActive, V.Desc, V.Offset, true); } -- GitLab From 267de8543c8671baa7e12c4d181e6c4e6e2342cd Mon Sep 17 00:00:00 2001 From: Rin Dobrescu Date: Wed, 22 May 2024 15:31:35 +0100 Subject: [PATCH 124/452] [llvm-mca][AArch64] Add AArch64 version of clearsSuperRegisters. (#92548) This patch overrides the clearsSuperRegisters method defined in MCInstrAnalysis to identify register writes that clear the upper portion of all super-registers on AArch64 architecture. On AArch64, a write to a general-purpose register of 32-bit data size is defined to use the lower 32-bits of the register and zero extend the upper 32-bits. Similarly, SIMD and FP instructions operating on scalar data only access the lower bits of the SIMD&FP register. The unused upper bits are cleared to zero on a write. This also applies to SIMD vector registers when the element size in bits multiplied by the number of lanes is lower than 128. The upper 64 bits of the vector register are cleared to zero on a write. --- .../MCTargetDesc/AArch64MCTargetDesc.cpp | 49 ++ .../AArch64/Neoverse/V1-clear-upper-regs.s | 791 +++++++++++++++++ .../AArch64/Neoverse/V2-clear-upper-regs.s | 812 ++++++++++++++++++ 3 files changed, 1652 insertions(+) create mode 100644 llvm/test/tools/llvm-mca/AArch64/Neoverse/V1-clear-upper-regs.s create mode 100644 llvm/test/tools/llvm-mca/AArch64/Neoverse/V2-clear-upper-regs.s diff --git a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64MCTargetDesc.cpp b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64MCTargetDesc.cpp index 0dd4a78f962d..6493a2ee4a93 100644 --- a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64MCTargetDesc.cpp +++ b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64MCTargetDesc.cpp @@ -430,6 +430,55 @@ public: return false; } + bool clearsSuperRegisters(const MCRegisterInfo &MRI, const MCInst &Inst, + APInt &Mask) const override { + const MCInstrDesc &Desc = Info->get(Inst.getOpcode()); + unsigned NumDefs = Desc.getNumDefs(); + unsigned NumImplicitDefs = Desc.implicit_defs().size(); + assert(Mask.getBitWidth() == NumDefs + NumImplicitDefs && + "Unexpected number of bits in the mask!"); + // 32-bit General Purpose Register class. + const MCRegisterClass &GPR32RC = MRI.getRegClass(AArch64::GPR32RegClassID); + // Floating Point Register classes. + const MCRegisterClass &FPR8RC = MRI.getRegClass(AArch64::FPR8RegClassID); + const MCRegisterClass &FPR16RC = MRI.getRegClass(AArch64::FPR16RegClassID); + const MCRegisterClass &FPR32RC = MRI.getRegClass(AArch64::FPR32RegClassID); + const MCRegisterClass &FPR64RC = MRI.getRegClass(AArch64::FPR64RegClassID); + const MCRegisterClass &FPR128RC = + MRI.getRegClass(AArch64::FPR128RegClassID); + + auto ClearsSuperReg = [=](unsigned RegID) { + // An update to the lower 32 bits of a 64 bit integer register is + // architecturally defined to zero extend the upper 32 bits on a write. + if (GPR32RC.contains(RegID)) + return true; + // SIMD&FP instructions operating on scalar data only acccess the lower + // bits of a register, the upper bits are zero extended on a write. For + // SIMD vector registers smaller than 128-bits, the upper 64-bits of the + // register are zero extended on a write. + // When VL is higher than 128 bits, any write to a SIMD&FP register sets + // bits higher than 128 to zero. + return FPR8RC.contains(RegID) || FPR16RC.contains(RegID) || + FPR32RC.contains(RegID) || FPR64RC.contains(RegID) || + FPR128RC.contains(RegID); + }; + + Mask.clearAllBits(); + for (unsigned I = 0, E = NumDefs; I < E; ++I) { + const MCOperand &Op = Inst.getOperand(I); + if (ClearsSuperReg(Op.getReg())) + Mask.setBit(I); + } + + for (unsigned I = 0, E = NumImplicitDefs; I < E; ++I) { + const MCPhysReg Reg = Desc.implicit_defs()[I]; + if (ClearsSuperReg(Reg)) + Mask.setBit(NumDefs + I); + } + + return Mask.getBoolValue(); + } + std::vector> findPltEntries(uint64_t PltSectionVA, ArrayRef PltContents, const Triple &TargetTriple) const override { diff --git a/llvm/test/tools/llvm-mca/AArch64/Neoverse/V1-clear-upper-regs.s b/llvm/test/tools/llvm-mca/AArch64/Neoverse/V1-clear-upper-regs.s new file mode 100644 index 000000000000..ab81f9fb04af --- /dev/null +++ b/llvm/test/tools/llvm-mca/AArch64/Neoverse/V1-clear-upper-regs.s @@ -0,0 +1,791 @@ +# NOTE: Assertions have been autogenerated by utils/update_mca_test_checks.py +# RUN: llvm-mca -mtriple=aarch64 -mcpu=neoverse-v1 --timeline --timeline-max-iterations=4 < %s | FileCheck %s + +# LLVM-MCA-BEGIN GPR32-bit +ldr w0, [sp] +add x0, x0, x0 +# LLVM-MCA-END + +# LLVM-MCA-BEGIN FPR8-bit +ldr b0, [sp] +fadd d0, d0, d0 +# LLVM-MCA-END + +# LLVM-MCA-BEGIN FPR16-bit +ldr h0, [sp] +fadd d0, d0, d0 +# LLVM-MCA-END + +# LLVM-MCA-BEGIN FPR32-bit +ldr s0, [sp] +fadd d0, d0, d0 +# LLVM-MCA-END + +# LLVM-MCA-BEGIN SIMD64-bit-b +ld1 {v0.8b}, [sp] +add v0.16b, v0.16b, v0.16b +# LLVM-MCA-END + +# LLVM-MCA-BEGIN SIMD64-bit-h +ld1 {v0.4h}, [sp] +add v0.8h, v0.8h, v0.8h +# LLVM-MCA-END + +# LLVM-MCA-BEGIN SIMD64-bit-s +ld1 {v0.2s}, [sp] +add v0.4s, v0.4s, v0.4s +# LLVM-MCA-END + +# LLVM-MCA-BEGIN SIMD64-bit-d +ld1 {v0.1d}, [sp] +add v0.2d, v0.2d, v0.2d +# LLVM-MCA-END + +# LLVM-MCA-BEGIN ins +ins v0.b[0], v1.b[1] +add v0.16b, v0.16b, v0.16b +# LLVM-MCA-END + +# LLVM-MCA-BEGIN lanewise-load +ld1 {v0.b}[0], [sp] +add v0.16b, v0.16b, v0.16b +# LLVM-MCA-END + +# CHECK: [0] Code Region - GPR32-bit + +# CHECK: Iterations: 100 +# CHECK-NEXT: Instructions: 200 +# CHECK-NEXT: Total Cycles: 41 +# CHECK-NEXT: Total uOps: 200 + +# CHECK: Dispatch Width: 15 +# CHECK-NEXT: uOps Per Cycle: 4.88 +# CHECK-NEXT: IPC: 4.88 +# CHECK-NEXT: Block RThroughput: 0.3 + +# CHECK: Instruction Info: +# CHECK-NEXT: [1]: #uOps +# CHECK-NEXT: [2]: Latency +# CHECK-NEXT: [3]: RThroughput +# CHECK-NEXT: [4]: MayLoad +# CHECK-NEXT: [5]: MayStore +# CHECK-NEXT: [6]: HasSideEffects (U) + +# CHECK: [1] [2] [3] [4] [5] [6] Instructions: +# CHECK-NEXT: 1 4 0.33 * ldr w0, [sp] +# CHECK-NEXT: 1 1 0.25 add x0, x0, x0 + +# CHECK: Resources: +# CHECK-NEXT: [0.0] - V1UnitB +# CHECK-NEXT: [0.1] - V1UnitB +# CHECK-NEXT: [1.0] - V1UnitD +# CHECK-NEXT: [1.1] - V1UnitD +# CHECK-NEXT: [2] - V1UnitL2 +# CHECK-NEXT: [3.0] - V1UnitL01 +# CHECK-NEXT: [3.1] - V1UnitL01 +# CHECK-NEXT: [4] - V1UnitM0 +# CHECK-NEXT: [5] - V1UnitM1 +# CHECK-NEXT: [6.0] - V1UnitS +# CHECK-NEXT: [6.1] - V1UnitS +# CHECK-NEXT: [7] - V1UnitV0 +# CHECK-NEXT: [8] - V1UnitV1 +# CHECK-NEXT: [9] - V1UnitV2 +# CHECK-NEXT: [10] - V1UnitV3 + +# CHECK: Resource pressure per iteration: +# CHECK-NEXT: [0.0] [0.1] [1.0] [1.1] [2] [3.0] [3.1] [4] [5] [6.0] [6.1] [7] [8] [9] [10] +# CHECK-NEXT: - - - - 0.33 0.33 0.34 0.22 0.22 0.28 0.28 - - - - + +# CHECK: Resource pressure by instruction: +# CHECK-NEXT: [0.0] [0.1] [1.0] [1.1] [2] [3.0] [3.1] [4] [5] [6.0] [6.1] [7] [8] [9] [10] Instructions: +# CHECK-NEXT: - - - - 0.33 0.33 0.34 - - - - - - - - ldr w0, [sp] +# CHECK-NEXT: - - - - - - - 0.22 0.22 0.28 0.28 - - - - add x0, x0, x0 + +# CHECK: Timeline view: +# CHECK-NEXT: Index 012345678 + +# CHECK: [0,0] DeeeeER . ldr w0, [sp] +# CHECK-NEXT: [0,1] D====eER. add x0, x0, x0 +# CHECK-NEXT: [1,0] DeeeeE-R. ldr w0, [sp] +# CHECK-NEXT: [1,1] D====eER. add x0, x0, x0 +# CHECK-NEXT: [2,0] DeeeeE-R. ldr w0, [sp] +# CHECK-NEXT: [2,1] D====eER. add x0, x0, x0 +# CHECK-NEXT: [3,0] D=eeeeER. ldr w0, [sp] +# CHECK-NEXT: [3,1] D=====eER add x0, x0, x0 + +# CHECK: Average Wait times (based on the timeline view): +# CHECK-NEXT: [0]: Executions +# CHECK-NEXT: [1]: Average time spent waiting in a scheduler's queue +# CHECK-NEXT: [2]: Average time spent waiting in a scheduler's queue while ready +# CHECK-NEXT: [3]: Average time elapsed from WB until retire stage + +# CHECK: [0] [1] [2] [3] +# CHECK-NEXT: 0. 4 1.3 1.3 0.5 ldr w0, [sp] +# CHECK-NEXT: 1. 4 5.3 0.0 0.0 add x0, x0, x0 +# CHECK-NEXT: 4 3.3 0.6 0.3 + +# CHECK: [1] Code Region - FPR8-bit + +# CHECK: Iterations: 100 +# CHECK-NEXT: Instructions: 200 +# CHECK-NEXT: Total Cycles: 44 +# CHECK-NEXT: Total uOps: 200 + +# CHECK: Dispatch Width: 15 +# CHECK-NEXT: uOps Per Cycle: 4.55 +# CHECK-NEXT: IPC: 4.55 +# CHECK-NEXT: Block RThroughput: 0.3 + +# CHECK: Instruction Info: +# CHECK-NEXT: [1]: #uOps +# CHECK-NEXT: [2]: Latency +# CHECK-NEXT: [3]: RThroughput +# CHECK-NEXT: [4]: MayLoad +# CHECK-NEXT: [5]: MayStore +# CHECK-NEXT: [6]: HasSideEffects (U) + +# CHECK: [1] [2] [3] [4] [5] [6] Instructions: +# CHECK-NEXT: 1 6 0.33 * ldr b0, [sp] +# CHECK-NEXT: 1 2 0.25 fadd d0, d0, d0 + +# CHECK: Resources: +# CHECK-NEXT: [0.0] - V1UnitB +# CHECK-NEXT: [0.1] - V1UnitB +# CHECK-NEXT: [1.0] - V1UnitD +# CHECK-NEXT: [1.1] - V1UnitD +# CHECK-NEXT: [2] - V1UnitL2 +# CHECK-NEXT: [3.0] - V1UnitL01 +# CHECK-NEXT: [3.1] - V1UnitL01 +# CHECK-NEXT: [4] - V1UnitM0 +# CHECK-NEXT: [5] - V1UnitM1 +# CHECK-NEXT: [6.0] - V1UnitS +# CHECK-NEXT: [6.1] - V1UnitS +# CHECK-NEXT: [7] - V1UnitV0 +# CHECK-NEXT: [8] - V1UnitV1 +# CHECK-NEXT: [9] - V1UnitV2 +# CHECK-NEXT: [10] - V1UnitV3 + +# CHECK: Resource pressure per iteration: +# CHECK-NEXT: [0.0] [0.1] [1.0] [1.1] [2] [3.0] [3.1] [4] [5] [6.0] [6.1] [7] [8] [9] [10] +# CHECK-NEXT: - - - - 0.33 0.33 0.34 - - - - 0.25 0.25 0.25 0.25 + +# CHECK: Resource pressure by instruction: +# CHECK-NEXT: [0.0] [0.1] [1.0] [1.1] [2] [3.0] [3.1] [4] [5] [6.0] [6.1] [7] [8] [9] [10] Instructions: +# CHECK-NEXT: - - - - 0.33 0.33 0.34 - - - - - - - - ldr b0, [sp] +# CHECK-NEXT: - - - - - - - - - - - 0.25 0.25 0.25 0.25 fadd d0, d0, d0 + +# CHECK: Timeline view: +# CHECK-NEXT: 01 +# CHECK-NEXT: Index 0123456789 + +# CHECK: [0,0] DeeeeeeER .. ldr b0, [sp] +# CHECK-NEXT: [0,1] D======eeER. fadd d0, d0, d0 +# CHECK-NEXT: [1,0] DeeeeeeE--R. ldr b0, [sp] +# CHECK-NEXT: [1,1] D======eeER. fadd d0, d0, d0 +# CHECK-NEXT: [2,0] DeeeeeeE--R. ldr b0, [sp] +# CHECK-NEXT: [2,1] D======eeER. fadd d0, d0, d0 +# CHECK-NEXT: [3,0] D=eeeeeeE-R. ldr b0, [sp] +# CHECK-NEXT: [3,1] D=======eeER fadd d0, d0, d0 + +# CHECK: Average Wait times (based on the timeline view): +# CHECK-NEXT: [0]: Executions +# CHECK-NEXT: [1]: Average time spent waiting in a scheduler's queue +# CHECK-NEXT: [2]: Average time spent waiting in a scheduler's queue while ready +# CHECK-NEXT: [3]: Average time elapsed from WB until retire stage + +# CHECK: [0] [1] [2] [3] +# CHECK-NEXT: 0. 4 1.3 1.3 1.3 ldr b0, [sp] +# CHECK-NEXT: 1. 4 7.3 0.0 0.0 fadd d0, d0, d0 +# CHECK-NEXT: 4 4.3 0.6 0.6 + +# CHECK: [2] Code Region - FPR16-bit + +# CHECK: Iterations: 100 +# CHECK-NEXT: Instructions: 200 +# CHECK-NEXT: Total Cycles: 44 +# CHECK-NEXT: Total uOps: 200 + +# CHECK: Dispatch Width: 15 +# CHECK-NEXT: uOps Per Cycle: 4.55 +# CHECK-NEXT: IPC: 4.55 +# CHECK-NEXT: Block RThroughput: 0.3 + +# CHECK: Instruction Info: +# CHECK-NEXT: [1]: #uOps +# CHECK-NEXT: [2]: Latency +# CHECK-NEXT: [3]: RThroughput +# CHECK-NEXT: [4]: MayLoad +# CHECK-NEXT: [5]: MayStore +# CHECK-NEXT: [6]: HasSideEffects (U) + +# CHECK: [1] [2] [3] [4] [5] [6] Instructions: +# CHECK-NEXT: 1 6 0.33 * ldr h0, [sp] +# CHECK-NEXT: 1 2 0.25 fadd d0, d0, d0 + +# CHECK: Resources: +# CHECK-NEXT: [0.0] - V1UnitB +# CHECK-NEXT: [0.1] - V1UnitB +# CHECK-NEXT: [1.0] - V1UnitD +# CHECK-NEXT: [1.1] - V1UnitD +# CHECK-NEXT: [2] - V1UnitL2 +# CHECK-NEXT: [3.0] - V1UnitL01 +# CHECK-NEXT: [3.1] - V1UnitL01 +# CHECK-NEXT: [4] - V1UnitM0 +# CHECK-NEXT: [5] - V1UnitM1 +# CHECK-NEXT: [6.0] - V1UnitS +# CHECK-NEXT: [6.1] - V1UnitS +# CHECK-NEXT: [7] - V1UnitV0 +# CHECK-NEXT: [8] - V1UnitV1 +# CHECK-NEXT: [9] - V1UnitV2 +# CHECK-NEXT: [10] - V1UnitV3 + +# CHECK: Resource pressure per iteration: +# CHECK-NEXT: [0.0] [0.1] [1.0] [1.1] [2] [3.0] [3.1] [4] [5] [6.0] [6.1] [7] [8] [9] [10] +# CHECK-NEXT: - - - - 0.33 0.33 0.34 - - - - 0.25 0.25 0.25 0.25 + +# CHECK: Resource pressure by instruction: +# CHECK-NEXT: [0.0] [0.1] [1.0] [1.1] [2] [3.0] [3.1] [4] [5] [6.0] [6.1] [7] [8] [9] [10] Instructions: +# CHECK-NEXT: - - - - 0.33 0.33 0.34 - - - - - - - - ldr h0, [sp] +# CHECK-NEXT: - - - - - - - - - - - 0.25 0.25 0.25 0.25 fadd d0, d0, d0 + +# CHECK: Timeline view: +# CHECK-NEXT: 01 +# CHECK-NEXT: Index 0123456789 + +# CHECK: [0,0] DeeeeeeER .. ldr h0, [sp] +# CHECK-NEXT: [0,1] D======eeER. fadd d0, d0, d0 +# CHECK-NEXT: [1,0] DeeeeeeE--R. ldr h0, [sp] +# CHECK-NEXT: [1,1] D======eeER. fadd d0, d0, d0 +# CHECK-NEXT: [2,0] DeeeeeeE--R. ldr h0, [sp] +# CHECK-NEXT: [2,1] D======eeER. fadd d0, d0, d0 +# CHECK-NEXT: [3,0] D=eeeeeeE-R. ldr h0, [sp] +# CHECK-NEXT: [3,1] D=======eeER fadd d0, d0, d0 + +# CHECK: Average Wait times (based on the timeline view): +# CHECK-NEXT: [0]: Executions +# CHECK-NEXT: [1]: Average time spent waiting in a scheduler's queue +# CHECK-NEXT: [2]: Average time spent waiting in a scheduler's queue while ready +# CHECK-NEXT: [3]: Average time elapsed from WB until retire stage + +# CHECK: [0] [1] [2] [3] +# CHECK-NEXT: 0. 4 1.3 1.3 1.3 ldr h0, [sp] +# CHECK-NEXT: 1. 4 7.3 0.0 0.0 fadd d0, d0, d0 +# CHECK-NEXT: 4 4.3 0.6 0.6 + +# CHECK: [3] Code Region - FPR32-bit + +# CHECK: Iterations: 100 +# CHECK-NEXT: Instructions: 200 +# CHECK-NEXT: Total Cycles: 44 +# CHECK-NEXT: Total uOps: 200 + +# CHECK: Dispatch Width: 15 +# CHECK-NEXT: uOps Per Cycle: 4.55 +# CHECK-NEXT: IPC: 4.55 +# CHECK-NEXT: Block RThroughput: 0.3 + +# CHECK: Instruction Info: +# CHECK-NEXT: [1]: #uOps +# CHECK-NEXT: [2]: Latency +# CHECK-NEXT: [3]: RThroughput +# CHECK-NEXT: [4]: MayLoad +# CHECK-NEXT: [5]: MayStore +# CHECK-NEXT: [6]: HasSideEffects (U) + +# CHECK: [1] [2] [3] [4] [5] [6] Instructions: +# CHECK-NEXT: 1 6 0.33 * ldr s0, [sp] +# CHECK-NEXT: 1 2 0.25 fadd d0, d0, d0 + +# CHECK: Resources: +# CHECK-NEXT: [0.0] - V1UnitB +# CHECK-NEXT: [0.1] - V1UnitB +# CHECK-NEXT: [1.0] - V1UnitD +# CHECK-NEXT: [1.1] - V1UnitD +# CHECK-NEXT: [2] - V1UnitL2 +# CHECK-NEXT: [3.0] - V1UnitL01 +# CHECK-NEXT: [3.1] - V1UnitL01 +# CHECK-NEXT: [4] - V1UnitM0 +# CHECK-NEXT: [5] - V1UnitM1 +# CHECK-NEXT: [6.0] - V1UnitS +# CHECK-NEXT: [6.1] - V1UnitS +# CHECK-NEXT: [7] - V1UnitV0 +# CHECK-NEXT: [8] - V1UnitV1 +# CHECK-NEXT: [9] - V1UnitV2 +# CHECK-NEXT: [10] - V1UnitV3 + +# CHECK: Resource pressure per iteration: +# CHECK-NEXT: [0.0] [0.1] [1.0] [1.1] [2] [3.0] [3.1] [4] [5] [6.0] [6.1] [7] [8] [9] [10] +# CHECK-NEXT: - - - - 0.33 0.33 0.34 - - - - 0.25 0.25 0.25 0.25 + +# CHECK: Resource pressure by instruction: +# CHECK-NEXT: [0.0] [0.1] [1.0] [1.1] [2] [3.0] [3.1] [4] [5] [6.0] [6.1] [7] [8] [9] [10] Instructions: +# CHECK-NEXT: - - - - 0.33 0.33 0.34 - - - - - - - - ldr s0, [sp] +# CHECK-NEXT: - - - - - - - - - - - 0.25 0.25 0.25 0.25 fadd d0, d0, d0 + +# CHECK: Timeline view: +# CHECK-NEXT: 01 +# CHECK-NEXT: Index 0123456789 + +# CHECK: [0,0] DeeeeeeER .. ldr s0, [sp] +# CHECK-NEXT: [0,1] D======eeER. fadd d0, d0, d0 +# CHECK-NEXT: [1,0] DeeeeeeE--R. ldr s0, [sp] +# CHECK-NEXT: [1,1] D======eeER. fadd d0, d0, d0 +# CHECK-NEXT: [2,0] DeeeeeeE--R. ldr s0, [sp] +# CHECK-NEXT: [2,1] D======eeER. fadd d0, d0, d0 +# CHECK-NEXT: [3,0] D=eeeeeeE-R. ldr s0, [sp] +# CHECK-NEXT: [3,1] D=======eeER fadd d0, d0, d0 + +# CHECK: Average Wait times (based on the timeline view): +# CHECK-NEXT: [0]: Executions +# CHECK-NEXT: [1]: Average time spent waiting in a scheduler's queue +# CHECK-NEXT: [2]: Average time spent waiting in a scheduler's queue while ready +# CHECK-NEXT: [3]: Average time elapsed from WB until retire stage + +# CHECK: [0] [1] [2] [3] +# CHECK-NEXT: 0. 4 1.3 1.3 1.3 ldr s0, [sp] +# CHECK-NEXT: 1. 4 7.3 0.0 0.0 fadd d0, d0, d0 +# CHECK-NEXT: 4 4.3 0.6 0.6 + +# CHECK: [4] Code Region - SIMD64-bit-b + +# CHECK: Iterations: 100 +# CHECK-NEXT: Instructions: 200 +# CHECK-NEXT: Total Cycles: 44 +# CHECK-NEXT: Total uOps: 200 + +# CHECK: Dispatch Width: 15 +# CHECK-NEXT: uOps Per Cycle: 4.55 +# CHECK-NEXT: IPC: 4.55 +# CHECK-NEXT: Block RThroughput: 0.3 + +# CHECK: Instruction Info: +# CHECK-NEXT: [1]: #uOps +# CHECK-NEXT: [2]: Latency +# CHECK-NEXT: [3]: RThroughput +# CHECK-NEXT: [4]: MayLoad +# CHECK-NEXT: [5]: MayStore +# CHECK-NEXT: [6]: HasSideEffects (U) + +# CHECK: [1] [2] [3] [4] [5] [6] Instructions: +# CHECK-NEXT: 1 6 0.33 * ld1 { v0.8b }, [sp] +# CHECK-NEXT: 1 2 0.25 add v0.16b, v0.16b, v0.16b + +# CHECK: Resources: +# CHECK-NEXT: [0.0] - V1UnitB +# CHECK-NEXT: [0.1] - V1UnitB +# CHECK-NEXT: [1.0] - V1UnitD +# CHECK-NEXT: [1.1] - V1UnitD +# CHECK-NEXT: [2] - V1UnitL2 +# CHECK-NEXT: [3.0] - V1UnitL01 +# CHECK-NEXT: [3.1] - V1UnitL01 +# CHECK-NEXT: [4] - V1UnitM0 +# CHECK-NEXT: [5] - V1UnitM1 +# CHECK-NEXT: [6.0] - V1UnitS +# CHECK-NEXT: [6.1] - V1UnitS +# CHECK-NEXT: [7] - V1UnitV0 +# CHECK-NEXT: [8] - V1UnitV1 +# CHECK-NEXT: [9] - V1UnitV2 +# CHECK-NEXT: [10] - V1UnitV3 + +# CHECK: Resource pressure per iteration: +# CHECK-NEXT: [0.0] [0.1] [1.0] [1.1] [2] [3.0] [3.1] [4] [5] [6.0] [6.1] [7] [8] [9] [10] +# CHECK-NEXT: - - - - 0.33 0.33 0.34 - - - - 0.25 0.25 0.25 0.25 + +# CHECK: Resource pressure by instruction: +# CHECK-NEXT: [0.0] [0.1] [1.0] [1.1] [2] [3.0] [3.1] [4] [5] [6.0] [6.1] [7] [8] [9] [10] Instructions: +# CHECK-NEXT: - - - - 0.33 0.33 0.34 - - - - - - - - ld1 { v0.8b }, [sp] +# CHECK-NEXT: - - - - - - - - - - - 0.25 0.25 0.25 0.25 add v0.16b, v0.16b, v0.16b + +# CHECK: Timeline view: +# CHECK-NEXT: 01 +# CHECK-NEXT: Index 0123456789 + +# CHECK: [0,0] DeeeeeeER .. ld1 { v0.8b }, [sp] +# CHECK-NEXT: [0,1] D======eeER. add v0.16b, v0.16b, v0.16b +# CHECK-NEXT: [1,0] DeeeeeeE--R. ld1 { v0.8b }, [sp] +# CHECK-NEXT: [1,1] D======eeER. add v0.16b, v0.16b, v0.16b +# CHECK-NEXT: [2,0] DeeeeeeE--R. ld1 { v0.8b }, [sp] +# CHECK-NEXT: [2,1] D======eeER. add v0.16b, v0.16b, v0.16b +# CHECK-NEXT: [3,0] D=eeeeeeE-R. ld1 { v0.8b }, [sp] +# CHECK-NEXT: [3,1] D=======eeER add v0.16b, v0.16b, v0.16b + +# CHECK: Average Wait times (based on the timeline view): +# CHECK-NEXT: [0]: Executions +# CHECK-NEXT: [1]: Average time spent waiting in a scheduler's queue +# CHECK-NEXT: [2]: Average time spent waiting in a scheduler's queue while ready +# CHECK-NEXT: [3]: Average time elapsed from WB until retire stage + +# CHECK: [0] [1] [2] [3] +# CHECK-NEXT: 0. 4 1.3 1.3 1.3 ld1 { v0.8b }, [sp] +# CHECK-NEXT: 1. 4 7.3 0.0 0.0 add v0.16b, v0.16b, v0.16b +# CHECK-NEXT: 4 4.3 0.6 0.6 + +# CHECK: [5] Code Region - SIMD64-bit-h + +# CHECK: Iterations: 100 +# CHECK-NEXT: Instructions: 200 +# CHECK-NEXT: Total Cycles: 44 +# CHECK-NEXT: Total uOps: 200 + +# CHECK: Dispatch Width: 15 +# CHECK-NEXT: uOps Per Cycle: 4.55 +# CHECK-NEXT: IPC: 4.55 +# CHECK-NEXT: Block RThroughput: 0.3 + +# CHECK: Instruction Info: +# CHECK-NEXT: [1]: #uOps +# CHECK-NEXT: [2]: Latency +# CHECK-NEXT: [3]: RThroughput +# CHECK-NEXT: [4]: MayLoad +# CHECK-NEXT: [5]: MayStore +# CHECK-NEXT: [6]: HasSideEffects (U) + +# CHECK: [1] [2] [3] [4] [5] [6] Instructions: +# CHECK-NEXT: 1 6 0.33 * ld1 { v0.4h }, [sp] +# CHECK-NEXT: 1 2 0.25 add v0.8h, v0.8h, v0.8h + +# CHECK: Resources: +# CHECK-NEXT: [0.0] - V1UnitB +# CHECK-NEXT: [0.1] - V1UnitB +# CHECK-NEXT: [1.0] - V1UnitD +# CHECK-NEXT: [1.1] - V1UnitD +# CHECK-NEXT: [2] - V1UnitL2 +# CHECK-NEXT: [3.0] - V1UnitL01 +# CHECK-NEXT: [3.1] - V1UnitL01 +# CHECK-NEXT: [4] - V1UnitM0 +# CHECK-NEXT: [5] - V1UnitM1 +# CHECK-NEXT: [6.0] - V1UnitS +# CHECK-NEXT: [6.1] - V1UnitS +# CHECK-NEXT: [7] - V1UnitV0 +# CHECK-NEXT: [8] - V1UnitV1 +# CHECK-NEXT: [9] - V1UnitV2 +# CHECK-NEXT: [10] - V1UnitV3 + +# CHECK: Resource pressure per iteration: +# CHECK-NEXT: [0.0] [0.1] [1.0] [1.1] [2] [3.0] [3.1] [4] [5] [6.0] [6.1] [7] [8] [9] [10] +# CHECK-NEXT: - - - - 0.33 0.33 0.34 - - - - 0.25 0.25 0.25 0.25 + +# CHECK: Resource pressure by instruction: +# CHECK-NEXT: [0.0] [0.1] [1.0] [1.1] [2] [3.0] [3.1] [4] [5] [6.0] [6.1] [7] [8] [9] [10] Instructions: +# CHECK-NEXT: - - - - 0.33 0.33 0.34 - - - - - - - - ld1 { v0.4h }, [sp] +# CHECK-NEXT: - - - - - - - - - - - 0.25 0.25 0.25 0.25 add v0.8h, v0.8h, v0.8h + +# CHECK: Timeline view: +# CHECK-NEXT: 01 +# CHECK-NEXT: Index 0123456789 + +# CHECK: [0,0] DeeeeeeER .. ld1 { v0.4h }, [sp] +# CHECK-NEXT: [0,1] D======eeER. add v0.8h, v0.8h, v0.8h +# CHECK-NEXT: [1,0] DeeeeeeE--R. ld1 { v0.4h }, [sp] +# CHECK-NEXT: [1,1] D======eeER. add v0.8h, v0.8h, v0.8h +# CHECK-NEXT: [2,0] DeeeeeeE--R. ld1 { v0.4h }, [sp] +# CHECK-NEXT: [2,1] D======eeER. add v0.8h, v0.8h, v0.8h +# CHECK-NEXT: [3,0] D=eeeeeeE-R. ld1 { v0.4h }, [sp] +# CHECK-NEXT: [3,1] D=======eeER add v0.8h, v0.8h, v0.8h + +# CHECK: Average Wait times (based on the timeline view): +# CHECK-NEXT: [0]: Executions +# CHECK-NEXT: [1]: Average time spent waiting in a scheduler's queue +# CHECK-NEXT: [2]: Average time spent waiting in a scheduler's queue while ready +# CHECK-NEXT: [3]: Average time elapsed from WB until retire stage + +# CHECK: [0] [1] [2] [3] +# CHECK-NEXT: 0. 4 1.3 1.3 1.3 ld1 { v0.4h }, [sp] +# CHECK-NEXT: 1. 4 7.3 0.0 0.0 add v0.8h, v0.8h, v0.8h +# CHECK-NEXT: 4 4.3 0.6 0.6 + +# CHECK: [6] Code Region - SIMD64-bit-s + +# CHECK: Iterations: 100 +# CHECK-NEXT: Instructions: 200 +# CHECK-NEXT: Total Cycles: 44 +# CHECK-NEXT: Total uOps: 200 + +# CHECK: Dispatch Width: 15 +# CHECK-NEXT: uOps Per Cycle: 4.55 +# CHECK-NEXT: IPC: 4.55 +# CHECK-NEXT: Block RThroughput: 0.3 + +# CHECK: Instruction Info: +# CHECK-NEXT: [1]: #uOps +# CHECK-NEXT: [2]: Latency +# CHECK-NEXT: [3]: RThroughput +# CHECK-NEXT: [4]: MayLoad +# CHECK-NEXT: [5]: MayStore +# CHECK-NEXT: [6]: HasSideEffects (U) + +# CHECK: [1] [2] [3] [4] [5] [6] Instructions: +# CHECK-NEXT: 1 6 0.33 * ld1 { v0.2s }, [sp] +# CHECK-NEXT: 1 2 0.25 add v0.4s, v0.4s, v0.4s + +# CHECK: Resources: +# CHECK-NEXT: [0.0] - V1UnitB +# CHECK-NEXT: [0.1] - V1UnitB +# CHECK-NEXT: [1.0] - V1UnitD +# CHECK-NEXT: [1.1] - V1UnitD +# CHECK-NEXT: [2] - V1UnitL2 +# CHECK-NEXT: [3.0] - V1UnitL01 +# CHECK-NEXT: [3.1] - V1UnitL01 +# CHECK-NEXT: [4] - V1UnitM0 +# CHECK-NEXT: [5] - V1UnitM1 +# CHECK-NEXT: [6.0] - V1UnitS +# CHECK-NEXT: [6.1] - V1UnitS +# CHECK-NEXT: [7] - V1UnitV0 +# CHECK-NEXT: [8] - V1UnitV1 +# CHECK-NEXT: [9] - V1UnitV2 +# CHECK-NEXT: [10] - V1UnitV3 + +# CHECK: Resource pressure per iteration: +# CHECK-NEXT: [0.0] [0.1] [1.0] [1.1] [2] [3.0] [3.1] [4] [5] [6.0] [6.1] [7] [8] [9] [10] +# CHECK-NEXT: - - - - 0.33 0.33 0.34 - - - - 0.25 0.25 0.25 0.25 + +# CHECK: Resource pressure by instruction: +# CHECK-NEXT: [0.0] [0.1] [1.0] [1.1] [2] [3.0] [3.1] [4] [5] [6.0] [6.1] [7] [8] [9] [10] Instructions: +# CHECK-NEXT: - - - - 0.33 0.33 0.34 - - - - - - - - ld1 { v0.2s }, [sp] +# CHECK-NEXT: - - - - - - - - - - - 0.25 0.25 0.25 0.25 add v0.4s, v0.4s, v0.4s + +# CHECK: Timeline view: +# CHECK-NEXT: 01 +# CHECK-NEXT: Index 0123456789 + +# CHECK: [0,0] DeeeeeeER .. ld1 { v0.2s }, [sp] +# CHECK-NEXT: [0,1] D======eeER. add v0.4s, v0.4s, v0.4s +# CHECK-NEXT: [1,0] DeeeeeeE--R. ld1 { v0.2s }, [sp] +# CHECK-NEXT: [1,1] D======eeER. add v0.4s, v0.4s, v0.4s +# CHECK-NEXT: [2,0] DeeeeeeE--R. ld1 { v0.2s }, [sp] +# CHECK-NEXT: [2,1] D======eeER. add v0.4s, v0.4s, v0.4s +# CHECK-NEXT: [3,0] D=eeeeeeE-R. ld1 { v0.2s }, [sp] +# CHECK-NEXT: [3,1] D=======eeER add v0.4s, v0.4s, v0.4s + +# CHECK: Average Wait times (based on the timeline view): +# CHECK-NEXT: [0]: Executions +# CHECK-NEXT: [1]: Average time spent waiting in a scheduler's queue +# CHECK-NEXT: [2]: Average time spent waiting in a scheduler's queue while ready +# CHECK-NEXT: [3]: Average time elapsed from WB until retire stage + +# CHECK: [0] [1] [2] [3] +# CHECK-NEXT: 0. 4 1.3 1.3 1.3 ld1 { v0.2s }, [sp] +# CHECK-NEXT: 1. 4 7.3 0.0 0.0 add v0.4s, v0.4s, v0.4s +# CHECK-NEXT: 4 4.3 0.6 0.6 + +# CHECK: [7] Code Region - SIMD64-bit-d + +# CHECK: Iterations: 100 +# CHECK-NEXT: Instructions: 200 +# CHECK-NEXT: Total Cycles: 44 +# CHECK-NEXT: Total uOps: 200 + +# CHECK: Dispatch Width: 15 +# CHECK-NEXT: uOps Per Cycle: 4.55 +# CHECK-NEXT: IPC: 4.55 +# CHECK-NEXT: Block RThroughput: 0.3 + +# CHECK: Instruction Info: +# CHECK-NEXT: [1]: #uOps +# CHECK-NEXT: [2]: Latency +# CHECK-NEXT: [3]: RThroughput +# CHECK-NEXT: [4]: MayLoad +# CHECK-NEXT: [5]: MayStore +# CHECK-NEXT: [6]: HasSideEffects (U) + +# CHECK: [1] [2] [3] [4] [5] [6] Instructions: +# CHECK-NEXT: 1 6 0.33 * ld1 { v0.1d }, [sp] +# CHECK-NEXT: 1 2 0.25 add v0.2d, v0.2d, v0.2d + +# CHECK: Resources: +# CHECK-NEXT: [0.0] - V1UnitB +# CHECK-NEXT: [0.1] - V1UnitB +# CHECK-NEXT: [1.0] - V1UnitD +# CHECK-NEXT: [1.1] - V1UnitD +# CHECK-NEXT: [2] - V1UnitL2 +# CHECK-NEXT: [3.0] - V1UnitL01 +# CHECK-NEXT: [3.1] - V1UnitL01 +# CHECK-NEXT: [4] - V1UnitM0 +# CHECK-NEXT: [5] - V1UnitM1 +# CHECK-NEXT: [6.0] - V1UnitS +# CHECK-NEXT: [6.1] - V1UnitS +# CHECK-NEXT: [7] - V1UnitV0 +# CHECK-NEXT: [8] - V1UnitV1 +# CHECK-NEXT: [9] - V1UnitV2 +# CHECK-NEXT: [10] - V1UnitV3 + +# CHECK: Resource pressure per iteration: +# CHECK-NEXT: [0.0] [0.1] [1.0] [1.1] [2] [3.0] [3.1] [4] [5] [6.0] [6.1] [7] [8] [9] [10] +# CHECK-NEXT: - - - - 0.33 0.33 0.34 - - - - 0.25 0.25 0.25 0.25 + +# CHECK: Resource pressure by instruction: +# CHECK-NEXT: [0.0] [0.1] [1.0] [1.1] [2] [3.0] [3.1] [4] [5] [6.0] [6.1] [7] [8] [9] [10] Instructions: +# CHECK-NEXT: - - - - 0.33 0.33 0.34 - - - - - - - - ld1 { v0.1d }, [sp] +# CHECK-NEXT: - - - - - - - - - - - 0.25 0.25 0.25 0.25 add v0.2d, v0.2d, v0.2d + +# CHECK: Timeline view: +# CHECK-NEXT: 01 +# CHECK-NEXT: Index 0123456789 + +# CHECK: [0,0] DeeeeeeER .. ld1 { v0.1d }, [sp] +# CHECK-NEXT: [0,1] D======eeER. add v0.2d, v0.2d, v0.2d +# CHECK-NEXT: [1,0] DeeeeeeE--R. ld1 { v0.1d }, [sp] +# CHECK-NEXT: [1,1] D======eeER. add v0.2d, v0.2d, v0.2d +# CHECK-NEXT: [2,0] DeeeeeeE--R. ld1 { v0.1d }, [sp] +# CHECK-NEXT: [2,1] D======eeER. add v0.2d, v0.2d, v0.2d +# CHECK-NEXT: [3,0] D=eeeeeeE-R. ld1 { v0.1d }, [sp] +# CHECK-NEXT: [3,1] D=======eeER add v0.2d, v0.2d, v0.2d + +# CHECK: Average Wait times (based on the timeline view): +# CHECK-NEXT: [0]: Executions +# CHECK-NEXT: [1]: Average time spent waiting in a scheduler's queue +# CHECK-NEXT: [2]: Average time spent waiting in a scheduler's queue while ready +# CHECK-NEXT: [3]: Average time elapsed from WB until retire stage + +# CHECK: [0] [1] [2] [3] +# CHECK-NEXT: 0. 4 1.3 1.3 1.3 ld1 { v0.1d }, [sp] +# CHECK-NEXT: 1. 4 7.3 0.0 0.0 add v0.2d, v0.2d, v0.2d +# CHECK-NEXT: 4 4.3 0.6 0.6 + +# CHECK: [8] Code Region - ins + +# CHECK: Iterations: 100 +# CHECK-NEXT: Instructions: 200 +# CHECK-NEXT: Total Cycles: 403 +# CHECK-NEXT: Total uOps: 200 + +# CHECK: Dispatch Width: 15 +# CHECK-NEXT: uOps Per Cycle: 0.50 +# CHECK-NEXT: IPC: 0.50 +# CHECK-NEXT: Block RThroughput: 0.5 + +# CHECK: Instruction Info: +# CHECK-NEXT: [1]: #uOps +# CHECK-NEXT: [2]: Latency +# CHECK-NEXT: [3]: RThroughput +# CHECK-NEXT: [4]: MayLoad +# CHECK-NEXT: [5]: MayStore +# CHECK-NEXT: [6]: HasSideEffects (U) + +# CHECK: [1] [2] [3] [4] [5] [6] Instructions: +# CHECK-NEXT: 1 2 0.25 mov v0.b[0], v1.b[1] +# CHECK-NEXT: 1 2 0.25 add v0.16b, v0.16b, v0.16b + +# CHECK: Resources: +# CHECK-NEXT: [0.0] - V1UnitB +# CHECK-NEXT: [0.1] - V1UnitB +# CHECK-NEXT: [1.0] - V1UnitD +# CHECK-NEXT: [1.1] - V1UnitD +# CHECK-NEXT: [2] - V1UnitL2 +# CHECK-NEXT: [3.0] - V1UnitL01 +# CHECK-NEXT: [3.1] - V1UnitL01 +# CHECK-NEXT: [4] - V1UnitM0 +# CHECK-NEXT: [5] - V1UnitM1 +# CHECK-NEXT: [6.0] - V1UnitS +# CHECK-NEXT: [6.1] - V1UnitS +# CHECK-NEXT: [7] - V1UnitV0 +# CHECK-NEXT: [8] - V1UnitV1 +# CHECK-NEXT: [9] - V1UnitV2 +# CHECK-NEXT: [10] - V1UnitV3 + +# CHECK: Resource pressure per iteration: +# CHECK-NEXT: [0.0] [0.1] [1.0] [1.1] [2] [3.0] [3.1] [4] [5] [6.0] [6.1] [7] [8] [9] [10] +# CHECK-NEXT: - - - - - - - - - - - 0.50 0.50 0.50 0.50 + +# CHECK: Resource pressure by instruction: +# CHECK-NEXT: [0.0] [0.1] [1.0] [1.1] [2] [3.0] [3.1] [4] [5] [6.0] [6.1] [7] [8] [9] [10] Instructions: +# CHECK-NEXT: - - - - - - - - - - - - 0.50 - 0.50 mov v0.b[0], v1.b[1] +# CHECK-NEXT: - - - - - - - - - - - 0.50 - 0.50 - add v0.16b, v0.16b, v0.16b + +# CHECK: Timeline view: +# CHECK-NEXT: 012345678 +# CHECK-NEXT: Index 0123456789 + +# CHECK: [0,0] DeeER. . . . mov v0.b[0], v1.b[1] +# CHECK-NEXT: [0,1] D==eeER . . . add v0.16b, v0.16b, v0.16b +# CHECK-NEXT: [1,0] D====eeER . . . mov v0.b[0], v1.b[1] +# CHECK-NEXT: [1,1] D======eeER . . add v0.16b, v0.16b, v0.16b +# CHECK-NEXT: [2,0] D========eeER . . mov v0.b[0], v1.b[1] +# CHECK-NEXT: [2,1] D==========eeER. . add v0.16b, v0.16b, v0.16b +# CHECK-NEXT: [3,0] D============eeER . mov v0.b[0], v1.b[1] +# CHECK-NEXT: [3,1] D==============eeER add v0.16b, v0.16b, v0.16b + +# CHECK: Average Wait times (based on the timeline view): +# CHECK-NEXT: [0]: Executions +# CHECK-NEXT: [1]: Average time spent waiting in a scheduler's queue +# CHECK-NEXT: [2]: Average time spent waiting in a scheduler's queue while ready +# CHECK-NEXT: [3]: Average time elapsed from WB until retire stage + +# CHECK: [0] [1] [2] [3] +# CHECK-NEXT: 0. 4 7.0 0.3 0.0 mov v0.b[0], v1.b[1] +# CHECK-NEXT: 1. 4 9.0 0.0 0.0 add v0.16b, v0.16b, v0.16b +# CHECK-NEXT: 4 8.0 0.1 0.0 + +# CHECK: [9] Code Region - lanewise-load + +# CHECK: Iterations: 100 +# CHECK-NEXT: Instructions: 200 +# CHECK-NEXT: Total Cycles: 1003 +# CHECK-NEXT: Total uOps: 300 + +# CHECK: Dispatch Width: 15 +# CHECK-NEXT: uOps Per Cycle: 0.30 +# CHECK-NEXT: IPC: 0.20 +# CHECK-NEXT: Block RThroughput: 0.5 + +# CHECK: Instruction Info: +# CHECK-NEXT: [1]: #uOps +# CHECK-NEXT: [2]: Latency +# CHECK-NEXT: [3]: RThroughput +# CHECK-NEXT: [4]: MayLoad +# CHECK-NEXT: [5]: MayStore +# CHECK-NEXT: [6]: HasSideEffects (U) + +# CHECK: [1] [2] [3] [4] [5] [6] Instructions: +# CHECK-NEXT: 2 8 0.33 * ld1 { v0.b }[0], [sp] +# CHECK-NEXT: 1 2 0.25 add v0.16b, v0.16b, v0.16b + +# CHECK: Resources: +# CHECK-NEXT: [0.0] - V1UnitB +# CHECK-NEXT: [0.1] - V1UnitB +# CHECK-NEXT: [1.0] - V1UnitD +# CHECK-NEXT: [1.1] - V1UnitD +# CHECK-NEXT: [2] - V1UnitL2 +# CHECK-NEXT: [3.0] - V1UnitL01 +# CHECK-NEXT: [3.1] - V1UnitL01 +# CHECK-NEXT: [4] - V1UnitM0 +# CHECK-NEXT: [5] - V1UnitM1 +# CHECK-NEXT: [6.0] - V1UnitS +# CHECK-NEXT: [6.1] - V1UnitS +# CHECK-NEXT: [7] - V1UnitV0 +# CHECK-NEXT: [8] - V1UnitV1 +# CHECK-NEXT: [9] - V1UnitV2 +# CHECK-NEXT: [10] - V1UnitV3 + +# CHECK: Resource pressure per iteration: +# CHECK-NEXT: [0.0] [0.1] [1.0] [1.1] [2] [3.0] [3.1] [4] [5] [6.0] [6.1] [7] [8] [9] [10] +# CHECK-NEXT: - - - - - 0.50 0.50 - - - - 0.50 0.50 0.50 0.50 + +# CHECK: Resource pressure by instruction: +# CHECK-NEXT: [0.0] [0.1] [1.0] [1.1] [2] [3.0] [3.1] [4] [5] [6.0] [6.1] [7] [8] [9] [10] Instructions: +# CHECK-NEXT: - - - - - 0.50 0.50 - - - - - 0.50 - 0.50 ld1 { v0.b }[0], [sp] +# CHECK-NEXT: - - - - - - - - - - - 0.50 - 0.50 - add v0.16b, v0.16b, v0.16b + +# CHECK: Timeline view: +# CHECK-NEXT: 0123456789 0123456789 +# CHECK-NEXT: Index 0123456789 0123456789 012 + +# CHECK: [0,0] DeeeeeeeeER . . . . . . . ld1 { v0.b }[0], [sp] +# CHECK-NEXT: [0,1] D========eeER . . . . . . . add v0.16b, v0.16b, v0.16b +# CHECK-NEXT: [1,0] D==========eeeeeeeeER . . . . . ld1 { v0.b }[0], [sp] +# CHECK-NEXT: [1,1] D==================eeER . . . . . add v0.16b, v0.16b, v0.16b +# CHECK-NEXT: [2,0] D====================eeeeeeeeER . . . ld1 { v0.b }[0], [sp] +# CHECK-NEXT: [2,1] D============================eeER . . . add v0.16b, v0.16b, v0.16b +# CHECK-NEXT: [3,0] D==============================eeeeeeeeER . ld1 { v0.b }[0], [sp] +# CHECK-NEXT: [3,1] D======================================eeER add v0.16b, v0.16b, v0.16b + +# CHECK: Average Wait times (based on the timeline view): +# CHECK-NEXT: [0]: Executions +# CHECK-NEXT: [1]: Average time spent waiting in a scheduler's queue +# CHECK-NEXT: [2]: Average time spent waiting in a scheduler's queue while ready +# CHECK-NEXT: [3]: Average time elapsed from WB until retire stage + +# CHECK: [0] [1] [2] [3] +# CHECK-NEXT: 0. 4 16.0 0.3 0.0 ld1 { v0.b }[0], [sp] +# CHECK-NEXT: 1. 4 24.0 0.0 0.0 add v0.16b, v0.16b, v0.16b +# CHECK-NEXT: 4 20.0 0.1 0.0 diff --git a/llvm/test/tools/llvm-mca/AArch64/Neoverse/V2-clear-upper-regs.s b/llvm/test/tools/llvm-mca/AArch64/Neoverse/V2-clear-upper-regs.s new file mode 100644 index 000000000000..fd2083dc1277 --- /dev/null +++ b/llvm/test/tools/llvm-mca/AArch64/Neoverse/V2-clear-upper-regs.s @@ -0,0 +1,812 @@ +# NOTE: Assertions have been autogenerated by utils/update_mca_test_checks.py +# RUN: llvm-mca -mtriple=aarch64 -mcpu=neoverse-v2 --timeline --timeline-max-iterations=4 < %s | FileCheck %s + +# LLVM-MCA-BEGIN FPR8-bit +ldr b0, [sp] +add z0.d, z0.d, z0.d +# LLVM-MCA-END + +# LLVM-MCA-BEGIN FPR16-bit +ldr h0, [sp] +add z0.d, z0.d, z0.d +# LLVM-MCA-END + +# LLVM-MCA-BEGIN FPR32-bit +ldr s0, [sp] +add z0.d, z0.d, z0.d +# LLVM-MCA-END + +# LLVM-MCA-BEGIN FPR64-bit +ldr d0, [sp] +add z0.d, z0.d, z0.d +# LLVM-MCA-END + +# LLVM-MCA-BEGIN FPR128-bit +ldr q0, [sp] +add z0.d, z0.d, z0.d +# LLVM-MCA-END + +# LLVM-MCA-BEGIN SIMD64-bit-b +ld1 {v0.8b}, [sp] +add z0.d, z0.d, z0.d +# LLVM-MCA-END + +# LLVM-MCA-BEGIN SIMD64-bit-h +ld1 {v0.4h}, [sp] +add z0.d, z0.d, z0.d +# LLVM-MCA-END + +# LLVM-MCA-BEGIN SIMD64-bit-s +ld1 {v0.2s}, [sp] +add z0.d, z0.d, z0.d +# LLVM-MCA-END + +# LLVM-MCA-BEGIN SIMD64-bit-d +ld1 {v0.1d}, [sp] +add z0.d, z0.d, z0.d +# LLVM-MCA-END + +# LLVM-MCA-BEGIN insr +insr z0.s, w0 +add z0.s, z0.s, z0.s +# LLVM-MCA-END + +# CHECK: [0] Code Region - FPR8-bit + +# CHECK: Iterations: 100 +# CHECK-NEXT: Instructions: 200 +# CHECK-NEXT: Total Cycles: 44 +# CHECK-NEXT: Total uOps: 200 + +# CHECK: Dispatch Width: 16 +# CHECK-NEXT: uOps Per Cycle: 4.55 +# CHECK-NEXT: IPC: 4.55 +# CHECK-NEXT: Block RThroughput: 0.3 + +# CHECK: Instruction Info: +# CHECK-NEXT: [1]: #uOps +# CHECK-NEXT: [2]: Latency +# CHECK-NEXT: [3]: RThroughput +# CHECK-NEXT: [4]: MayLoad +# CHECK-NEXT: [5]: MayStore +# CHECK-NEXT: [6]: HasSideEffects (U) + +# CHECK: [1] [2] [3] [4] [5] [6] Instructions: +# CHECK-NEXT: 1 6 0.33 * ldr b0, [sp] +# CHECK-NEXT: 1 2 0.25 add z0.d, z0.d, z0.d + +# CHECK: Resources: +# CHECK-NEXT: [0.0] - V2UnitB +# CHECK-NEXT: [0.1] - V2UnitB +# CHECK-NEXT: [1.0] - V2UnitD +# CHECK-NEXT: [1.1] - V2UnitD +# CHECK-NEXT: [2] - V2UnitL2 +# CHECK-NEXT: [3.0] - V2UnitL01 +# CHECK-NEXT: [3.1] - V2UnitL01 +# CHECK-NEXT: [4] - V2UnitM0 +# CHECK-NEXT: [5] - V2UnitM1 +# CHECK-NEXT: [6] - V2UnitS0 +# CHECK-NEXT: [7] - V2UnitS1 +# CHECK-NEXT: [8] - V2UnitS2 +# CHECK-NEXT: [9] - V2UnitS3 +# CHECK-NEXT: [10] - V2UnitV0 +# CHECK-NEXT: [11] - V2UnitV1 +# CHECK-NEXT: [12] - V2UnitV2 +# CHECK-NEXT: [13] - V2UnitV3 + +# CHECK: Resource pressure per iteration: +# CHECK-NEXT: [0.0] [0.1] [1.0] [1.1] [2] [3.0] [3.1] [4] [5] [6] [7] [8] [9] [10] [11] [12] [13] +# CHECK-NEXT: - - - - 0.33 0.33 0.34 - - - - - - 0.25 0.25 0.25 0.25 + +# CHECK: Resource pressure by instruction: +# CHECK-NEXT: [0.0] [0.1] [1.0] [1.1] [2] [3.0] [3.1] [4] [5] [6] [7] [8] [9] [10] [11] [12] [13] Instructions: +# CHECK-NEXT: - - - - 0.33 0.33 0.34 - - - - - - - - - - ldr b0, [sp] +# CHECK-NEXT: - - - - - - - - - - - - - 0.25 0.25 0.25 0.25 add z0.d, z0.d, z0.d + +# CHECK: Timeline view: +# CHECK-NEXT: 01 +# CHECK-NEXT: Index 0123456789 + +# CHECK: [0,0] DeeeeeeER .. ldr b0, [sp] +# CHECK-NEXT: [0,1] D======eeER. add z0.d, z0.d, z0.d +# CHECK-NEXT: [1,0] DeeeeeeE--R. ldr b0, [sp] +# CHECK-NEXT: [1,1] D======eeER. add z0.d, z0.d, z0.d +# CHECK-NEXT: [2,0] DeeeeeeE--R. ldr b0, [sp] +# CHECK-NEXT: [2,1] D======eeER. add z0.d, z0.d, z0.d +# CHECK-NEXT: [3,0] D=eeeeeeE-R. ldr b0, [sp] +# CHECK-NEXT: [3,1] D=======eeER add z0.d, z0.d, z0.d + +# CHECK: Average Wait times (based on the timeline view): +# CHECK-NEXT: [0]: Executions +# CHECK-NEXT: [1]: Average time spent waiting in a scheduler's queue +# CHECK-NEXT: [2]: Average time spent waiting in a scheduler's queue while ready +# CHECK-NEXT: [3]: Average time elapsed from WB until retire stage + +# CHECK: [0] [1] [2] [3] +# CHECK-NEXT: 0. 4 1.3 1.3 1.3 ldr b0, [sp] +# CHECK-NEXT: 1. 4 7.3 0.0 0.0 add z0.d, z0.d, z0.d +# CHECK-NEXT: 4 4.3 0.6 0.6 + +# CHECK: [1] Code Region - FPR16-bit + +# CHECK: Iterations: 100 +# CHECK-NEXT: Instructions: 200 +# CHECK-NEXT: Total Cycles: 44 +# CHECK-NEXT: Total uOps: 200 + +# CHECK: Dispatch Width: 16 +# CHECK-NEXT: uOps Per Cycle: 4.55 +# CHECK-NEXT: IPC: 4.55 +# CHECK-NEXT: Block RThroughput: 0.3 + +# CHECK: Instruction Info: +# CHECK-NEXT: [1]: #uOps +# CHECK-NEXT: [2]: Latency +# CHECK-NEXT: [3]: RThroughput +# CHECK-NEXT: [4]: MayLoad +# CHECK-NEXT: [5]: MayStore +# CHECK-NEXT: [6]: HasSideEffects (U) + +# CHECK: [1] [2] [3] [4] [5] [6] Instructions: +# CHECK-NEXT: 1 6 0.33 * ldr h0, [sp] +# CHECK-NEXT: 1 2 0.25 add z0.d, z0.d, z0.d + +# CHECK: Resources: +# CHECK-NEXT: [0.0] - V2UnitB +# CHECK-NEXT: [0.1] - V2UnitB +# CHECK-NEXT: [1.0] - V2UnitD +# CHECK-NEXT: [1.1] - V2UnitD +# CHECK-NEXT: [2] - V2UnitL2 +# CHECK-NEXT: [3.0] - V2UnitL01 +# CHECK-NEXT: [3.1] - V2UnitL01 +# CHECK-NEXT: [4] - V2UnitM0 +# CHECK-NEXT: [5] - V2UnitM1 +# CHECK-NEXT: [6] - V2UnitS0 +# CHECK-NEXT: [7] - V2UnitS1 +# CHECK-NEXT: [8] - V2UnitS2 +# CHECK-NEXT: [9] - V2UnitS3 +# CHECK-NEXT: [10] - V2UnitV0 +# CHECK-NEXT: [11] - V2UnitV1 +# CHECK-NEXT: [12] - V2UnitV2 +# CHECK-NEXT: [13] - V2UnitV3 + +# CHECK: Resource pressure per iteration: +# CHECK-NEXT: [0.0] [0.1] [1.0] [1.1] [2] [3.0] [3.1] [4] [5] [6] [7] [8] [9] [10] [11] [12] [13] +# CHECK-NEXT: - - - - 0.33 0.33 0.34 - - - - - - 0.25 0.25 0.25 0.25 + +# CHECK: Resource pressure by instruction: +# CHECK-NEXT: [0.0] [0.1] [1.0] [1.1] [2] [3.0] [3.1] [4] [5] [6] [7] [8] [9] [10] [11] [12] [13] Instructions: +# CHECK-NEXT: - - - - 0.33 0.33 0.34 - - - - - - - - - - ldr h0, [sp] +# CHECK-NEXT: - - - - - - - - - - - - - 0.25 0.25 0.25 0.25 add z0.d, z0.d, z0.d + +# CHECK: Timeline view: +# CHECK-NEXT: 01 +# CHECK-NEXT: Index 0123456789 + +# CHECK: [0,0] DeeeeeeER .. ldr h0, [sp] +# CHECK-NEXT: [0,1] D======eeER. add z0.d, z0.d, z0.d +# CHECK-NEXT: [1,0] DeeeeeeE--R. ldr h0, [sp] +# CHECK-NEXT: [1,1] D======eeER. add z0.d, z0.d, z0.d +# CHECK-NEXT: [2,0] DeeeeeeE--R. ldr h0, [sp] +# CHECK-NEXT: [2,1] D======eeER. add z0.d, z0.d, z0.d +# CHECK-NEXT: [3,0] D=eeeeeeE-R. ldr h0, [sp] +# CHECK-NEXT: [3,1] D=======eeER add z0.d, z0.d, z0.d + +# CHECK: Average Wait times (based on the timeline view): +# CHECK-NEXT: [0]: Executions +# CHECK-NEXT: [1]: Average time spent waiting in a scheduler's queue +# CHECK-NEXT: [2]: Average time spent waiting in a scheduler's queue while ready +# CHECK-NEXT: [3]: Average time elapsed from WB until retire stage + +# CHECK: [0] [1] [2] [3] +# CHECK-NEXT: 0. 4 1.3 1.3 1.3 ldr h0, [sp] +# CHECK-NEXT: 1. 4 7.3 0.0 0.0 add z0.d, z0.d, z0.d +# CHECK-NEXT: 4 4.3 0.6 0.6 + +# CHECK: [2] Code Region - FPR32-bit + +# CHECK: Iterations: 100 +# CHECK-NEXT: Instructions: 200 +# CHECK-NEXT: Total Cycles: 44 +# CHECK-NEXT: Total uOps: 200 + +# CHECK: Dispatch Width: 16 +# CHECK-NEXT: uOps Per Cycle: 4.55 +# CHECK-NEXT: IPC: 4.55 +# CHECK-NEXT: Block RThroughput: 0.3 + +# CHECK: Instruction Info: +# CHECK-NEXT: [1]: #uOps +# CHECK-NEXT: [2]: Latency +# CHECK-NEXT: [3]: RThroughput +# CHECK-NEXT: [4]: MayLoad +# CHECK-NEXT: [5]: MayStore +# CHECK-NEXT: [6]: HasSideEffects (U) + +# CHECK: [1] [2] [3] [4] [5] [6] Instructions: +# CHECK-NEXT: 1 6 0.33 * ldr s0, [sp] +# CHECK-NEXT: 1 2 0.25 add z0.d, z0.d, z0.d + +# CHECK: Resources: +# CHECK-NEXT: [0.0] - V2UnitB +# CHECK-NEXT: [0.1] - V2UnitB +# CHECK-NEXT: [1.0] - V2UnitD +# CHECK-NEXT: [1.1] - V2UnitD +# CHECK-NEXT: [2] - V2UnitL2 +# CHECK-NEXT: [3.0] - V2UnitL01 +# CHECK-NEXT: [3.1] - V2UnitL01 +# CHECK-NEXT: [4] - V2UnitM0 +# CHECK-NEXT: [5] - V2UnitM1 +# CHECK-NEXT: [6] - V2UnitS0 +# CHECK-NEXT: [7] - V2UnitS1 +# CHECK-NEXT: [8] - V2UnitS2 +# CHECK-NEXT: [9] - V2UnitS3 +# CHECK-NEXT: [10] - V2UnitV0 +# CHECK-NEXT: [11] - V2UnitV1 +# CHECK-NEXT: [12] - V2UnitV2 +# CHECK-NEXT: [13] - V2UnitV3 + +# CHECK: Resource pressure per iteration: +# CHECK-NEXT: [0.0] [0.1] [1.0] [1.1] [2] [3.0] [3.1] [4] [5] [6] [7] [8] [9] [10] [11] [12] [13] +# CHECK-NEXT: - - - - 0.33 0.33 0.34 - - - - - - 0.25 0.25 0.25 0.25 + +# CHECK: Resource pressure by instruction: +# CHECK-NEXT: [0.0] [0.1] [1.0] [1.1] [2] [3.0] [3.1] [4] [5] [6] [7] [8] [9] [10] [11] [12] [13] Instructions: +# CHECK-NEXT: - - - - 0.33 0.33 0.34 - - - - - - - - - - ldr s0, [sp] +# CHECK-NEXT: - - - - - - - - - - - - - 0.25 0.25 0.25 0.25 add z0.d, z0.d, z0.d + +# CHECK: Timeline view: +# CHECK-NEXT: 01 +# CHECK-NEXT: Index 0123456789 + +# CHECK: [0,0] DeeeeeeER .. ldr s0, [sp] +# CHECK-NEXT: [0,1] D======eeER. add z0.d, z0.d, z0.d +# CHECK-NEXT: [1,0] DeeeeeeE--R. ldr s0, [sp] +# CHECK-NEXT: [1,1] D======eeER. add z0.d, z0.d, z0.d +# CHECK-NEXT: [2,0] DeeeeeeE--R. ldr s0, [sp] +# CHECK-NEXT: [2,1] D======eeER. add z0.d, z0.d, z0.d +# CHECK-NEXT: [3,0] D=eeeeeeE-R. ldr s0, [sp] +# CHECK-NEXT: [3,1] D=======eeER add z0.d, z0.d, z0.d + +# CHECK: Average Wait times (based on the timeline view): +# CHECK-NEXT: [0]: Executions +# CHECK-NEXT: [1]: Average time spent waiting in a scheduler's queue +# CHECK-NEXT: [2]: Average time spent waiting in a scheduler's queue while ready +# CHECK-NEXT: [3]: Average time elapsed from WB until retire stage + +# CHECK: [0] [1] [2] [3] +# CHECK-NEXT: 0. 4 1.3 1.3 1.3 ldr s0, [sp] +# CHECK-NEXT: 1. 4 7.3 0.0 0.0 add z0.d, z0.d, z0.d +# CHECK-NEXT: 4 4.3 0.6 0.6 + +# CHECK: [3] Code Region - FPR64-bit + +# CHECK: Iterations: 100 +# CHECK-NEXT: Instructions: 200 +# CHECK-NEXT: Total Cycles: 44 +# CHECK-NEXT: Total uOps: 200 + +# CHECK: Dispatch Width: 16 +# CHECK-NEXT: uOps Per Cycle: 4.55 +# CHECK-NEXT: IPC: 4.55 +# CHECK-NEXT: Block RThroughput: 0.3 + +# CHECK: Instruction Info: +# CHECK-NEXT: [1]: #uOps +# CHECK-NEXT: [2]: Latency +# CHECK-NEXT: [3]: RThroughput +# CHECK-NEXT: [4]: MayLoad +# CHECK-NEXT: [5]: MayStore +# CHECK-NEXT: [6]: HasSideEffects (U) + +# CHECK: [1] [2] [3] [4] [5] [6] Instructions: +# CHECK-NEXT: 1 6 0.33 * ldr d0, [sp] +# CHECK-NEXT: 1 2 0.25 add z0.d, z0.d, z0.d + +# CHECK: Resources: +# CHECK-NEXT: [0.0] - V2UnitB +# CHECK-NEXT: [0.1] - V2UnitB +# CHECK-NEXT: [1.0] - V2UnitD +# CHECK-NEXT: [1.1] - V2UnitD +# CHECK-NEXT: [2] - V2UnitL2 +# CHECK-NEXT: [3.0] - V2UnitL01 +# CHECK-NEXT: [3.1] - V2UnitL01 +# CHECK-NEXT: [4] - V2UnitM0 +# CHECK-NEXT: [5] - V2UnitM1 +# CHECK-NEXT: [6] - V2UnitS0 +# CHECK-NEXT: [7] - V2UnitS1 +# CHECK-NEXT: [8] - V2UnitS2 +# CHECK-NEXT: [9] - V2UnitS3 +# CHECK-NEXT: [10] - V2UnitV0 +# CHECK-NEXT: [11] - V2UnitV1 +# CHECK-NEXT: [12] - V2UnitV2 +# CHECK-NEXT: [13] - V2UnitV3 + +# CHECK: Resource pressure per iteration: +# CHECK-NEXT: [0.0] [0.1] [1.0] [1.1] [2] [3.0] [3.1] [4] [5] [6] [7] [8] [9] [10] [11] [12] [13] +# CHECK-NEXT: - - - - 0.33 0.33 0.34 - - - - - - 0.25 0.25 0.25 0.25 + +# CHECK: Resource pressure by instruction: +# CHECK-NEXT: [0.0] [0.1] [1.0] [1.1] [2] [3.0] [3.1] [4] [5] [6] [7] [8] [9] [10] [11] [12] [13] Instructions: +# CHECK-NEXT: - - - - 0.33 0.33 0.34 - - - - - - - - - - ldr d0, [sp] +# CHECK-NEXT: - - - - - - - - - - - - - 0.25 0.25 0.25 0.25 add z0.d, z0.d, z0.d + +# CHECK: Timeline view: +# CHECK-NEXT: 01 +# CHECK-NEXT: Index 0123456789 + +# CHECK: [0,0] DeeeeeeER .. ldr d0, [sp] +# CHECK-NEXT: [0,1] D======eeER. add z0.d, z0.d, z0.d +# CHECK-NEXT: [1,0] DeeeeeeE--R. ldr d0, [sp] +# CHECK-NEXT: [1,1] D======eeER. add z0.d, z0.d, z0.d +# CHECK-NEXT: [2,0] DeeeeeeE--R. ldr d0, [sp] +# CHECK-NEXT: [2,1] D======eeER. add z0.d, z0.d, z0.d +# CHECK-NEXT: [3,0] D=eeeeeeE-R. ldr d0, [sp] +# CHECK-NEXT: [3,1] D=======eeER add z0.d, z0.d, z0.d + +# CHECK: Average Wait times (based on the timeline view): +# CHECK-NEXT: [0]: Executions +# CHECK-NEXT: [1]: Average time spent waiting in a scheduler's queue +# CHECK-NEXT: [2]: Average time spent waiting in a scheduler's queue while ready +# CHECK-NEXT: [3]: Average time elapsed from WB until retire stage + +# CHECK: [0] [1] [2] [3] +# CHECK-NEXT: 0. 4 1.3 1.3 1.3 ldr d0, [sp] +# CHECK-NEXT: 1. 4 7.3 0.0 0.0 add z0.d, z0.d, z0.d +# CHECK-NEXT: 4 4.3 0.6 0.6 + +# CHECK: [4] Code Region - FPR128-bit + +# CHECK: Iterations: 100 +# CHECK-NEXT: Instructions: 200 +# CHECK-NEXT: Total Cycles: 44 +# CHECK-NEXT: Total uOps: 200 + +# CHECK: Dispatch Width: 16 +# CHECK-NEXT: uOps Per Cycle: 4.55 +# CHECK-NEXT: IPC: 4.55 +# CHECK-NEXT: Block RThroughput: 0.3 + +# CHECK: Instruction Info: +# CHECK-NEXT: [1]: #uOps +# CHECK-NEXT: [2]: Latency +# CHECK-NEXT: [3]: RThroughput +# CHECK-NEXT: [4]: MayLoad +# CHECK-NEXT: [5]: MayStore +# CHECK-NEXT: [6]: HasSideEffects (U) + +# CHECK: [1] [2] [3] [4] [5] [6] Instructions: +# CHECK-NEXT: 1 6 0.33 * ldr q0, [sp] +# CHECK-NEXT: 1 2 0.25 add z0.d, z0.d, z0.d + +# CHECK: Resources: +# CHECK-NEXT: [0.0] - V2UnitB +# CHECK-NEXT: [0.1] - V2UnitB +# CHECK-NEXT: [1.0] - V2UnitD +# CHECK-NEXT: [1.1] - V2UnitD +# CHECK-NEXT: [2] - V2UnitL2 +# CHECK-NEXT: [3.0] - V2UnitL01 +# CHECK-NEXT: [3.1] - V2UnitL01 +# CHECK-NEXT: [4] - V2UnitM0 +# CHECK-NEXT: [5] - V2UnitM1 +# CHECK-NEXT: [6] - V2UnitS0 +# CHECK-NEXT: [7] - V2UnitS1 +# CHECK-NEXT: [8] - V2UnitS2 +# CHECK-NEXT: [9] - V2UnitS3 +# CHECK-NEXT: [10] - V2UnitV0 +# CHECK-NEXT: [11] - V2UnitV1 +# CHECK-NEXT: [12] - V2UnitV2 +# CHECK-NEXT: [13] - V2UnitV3 + +# CHECK: Resource pressure per iteration: +# CHECK-NEXT: [0.0] [0.1] [1.0] [1.1] [2] [3.0] [3.1] [4] [5] [6] [7] [8] [9] [10] [11] [12] [13] +# CHECK-NEXT: - - - - 0.33 0.33 0.34 - - - - - - 0.25 0.25 0.25 0.25 + +# CHECK: Resource pressure by instruction: +# CHECK-NEXT: [0.0] [0.1] [1.0] [1.1] [2] [3.0] [3.1] [4] [5] [6] [7] [8] [9] [10] [11] [12] [13] Instructions: +# CHECK-NEXT: - - - - 0.33 0.33 0.34 - - - - - - - - - - ldr q0, [sp] +# CHECK-NEXT: - - - - - - - - - - - - - 0.25 0.25 0.25 0.25 add z0.d, z0.d, z0.d + +# CHECK: Timeline view: +# CHECK-NEXT: 01 +# CHECK-NEXT: Index 0123456789 + +# CHECK: [0,0] DeeeeeeER .. ldr q0, [sp] +# CHECK-NEXT: [0,1] D======eeER. add z0.d, z0.d, z0.d +# CHECK-NEXT: [1,0] DeeeeeeE--R. ldr q0, [sp] +# CHECK-NEXT: [1,1] D======eeER. add z0.d, z0.d, z0.d +# CHECK-NEXT: [2,0] DeeeeeeE--R. ldr q0, [sp] +# CHECK-NEXT: [2,1] D======eeER. add z0.d, z0.d, z0.d +# CHECK-NEXT: [3,0] D=eeeeeeE-R. ldr q0, [sp] +# CHECK-NEXT: [3,1] D=======eeER add z0.d, z0.d, z0.d + +# CHECK: Average Wait times (based on the timeline view): +# CHECK-NEXT: [0]: Executions +# CHECK-NEXT: [1]: Average time spent waiting in a scheduler's queue +# CHECK-NEXT: [2]: Average time spent waiting in a scheduler's queue while ready +# CHECK-NEXT: [3]: Average time elapsed from WB until retire stage + +# CHECK: [0] [1] [2] [3] +# CHECK-NEXT: 0. 4 1.3 1.3 1.3 ldr q0, [sp] +# CHECK-NEXT: 1. 4 7.3 0.0 0.0 add z0.d, z0.d, z0.d +# CHECK-NEXT: 4 4.3 0.6 0.6 + +# CHECK: [5] Code Region - SIMD64-bit-b + +# CHECK: Iterations: 100 +# CHECK-NEXT: Instructions: 200 +# CHECK-NEXT: Total Cycles: 44 +# CHECK-NEXT: Total uOps: 200 + +# CHECK: Dispatch Width: 16 +# CHECK-NEXT: uOps Per Cycle: 4.55 +# CHECK-NEXT: IPC: 4.55 +# CHECK-NEXT: Block RThroughput: 0.3 + +# CHECK: Instruction Info: +# CHECK-NEXT: [1]: #uOps +# CHECK-NEXT: [2]: Latency +# CHECK-NEXT: [3]: RThroughput +# CHECK-NEXT: [4]: MayLoad +# CHECK-NEXT: [5]: MayStore +# CHECK-NEXT: [6]: HasSideEffects (U) + +# CHECK: [1] [2] [3] [4] [5] [6] Instructions: +# CHECK-NEXT: 1 6 0.33 * ld1 { v0.8b }, [sp] +# CHECK-NEXT: 1 2 0.25 add z0.d, z0.d, z0.d + +# CHECK: Resources: +# CHECK-NEXT: [0.0] - V2UnitB +# CHECK-NEXT: [0.1] - V2UnitB +# CHECK-NEXT: [1.0] - V2UnitD +# CHECK-NEXT: [1.1] - V2UnitD +# CHECK-NEXT: [2] - V2UnitL2 +# CHECK-NEXT: [3.0] - V2UnitL01 +# CHECK-NEXT: [3.1] - V2UnitL01 +# CHECK-NEXT: [4] - V2UnitM0 +# CHECK-NEXT: [5] - V2UnitM1 +# CHECK-NEXT: [6] - V2UnitS0 +# CHECK-NEXT: [7] - V2UnitS1 +# CHECK-NEXT: [8] - V2UnitS2 +# CHECK-NEXT: [9] - V2UnitS3 +# CHECK-NEXT: [10] - V2UnitV0 +# CHECK-NEXT: [11] - V2UnitV1 +# CHECK-NEXT: [12] - V2UnitV2 +# CHECK-NEXT: [13] - V2UnitV3 + +# CHECK: Resource pressure per iteration: +# CHECK-NEXT: [0.0] [0.1] [1.0] [1.1] [2] [3.0] [3.1] [4] [5] [6] [7] [8] [9] [10] [11] [12] [13] +# CHECK-NEXT: - - - - 0.33 0.33 0.34 - - - - - - 0.25 0.25 0.25 0.25 + +# CHECK: Resource pressure by instruction: +# CHECK-NEXT: [0.0] [0.1] [1.0] [1.1] [2] [3.0] [3.1] [4] [5] [6] [7] [8] [9] [10] [11] [12] [13] Instructions: +# CHECK-NEXT: - - - - 0.33 0.33 0.34 - - - - - - - - - - ld1 { v0.8b }, [sp] +# CHECK-NEXT: - - - - - - - - - - - - - 0.25 0.25 0.25 0.25 add z0.d, z0.d, z0.d + +# CHECK: Timeline view: +# CHECK-NEXT: 01 +# CHECK-NEXT: Index 0123456789 + +# CHECK: [0,0] DeeeeeeER .. ld1 { v0.8b }, [sp] +# CHECK-NEXT: [0,1] D======eeER. add z0.d, z0.d, z0.d +# CHECK-NEXT: [1,0] DeeeeeeE--R. ld1 { v0.8b }, [sp] +# CHECK-NEXT: [1,1] D======eeER. add z0.d, z0.d, z0.d +# CHECK-NEXT: [2,0] DeeeeeeE--R. ld1 { v0.8b }, [sp] +# CHECK-NEXT: [2,1] D======eeER. add z0.d, z0.d, z0.d +# CHECK-NEXT: [3,0] D=eeeeeeE-R. ld1 { v0.8b }, [sp] +# CHECK-NEXT: [3,1] D=======eeER add z0.d, z0.d, z0.d + +# CHECK: Average Wait times (based on the timeline view): +# CHECK-NEXT: [0]: Executions +# CHECK-NEXT: [1]: Average time spent waiting in a scheduler's queue +# CHECK-NEXT: [2]: Average time spent waiting in a scheduler's queue while ready +# CHECK-NEXT: [3]: Average time elapsed from WB until retire stage + +# CHECK: [0] [1] [2] [3] +# CHECK-NEXT: 0. 4 1.3 1.3 1.3 ld1 { v0.8b }, [sp] +# CHECK-NEXT: 1. 4 7.3 0.0 0.0 add z0.d, z0.d, z0.d +# CHECK-NEXT: 4 4.3 0.6 0.6 + +# CHECK: [6] Code Region - SIMD64-bit-h + +# CHECK: Iterations: 100 +# CHECK-NEXT: Instructions: 200 +# CHECK-NEXT: Total Cycles: 44 +# CHECK-NEXT: Total uOps: 200 + +# CHECK: Dispatch Width: 16 +# CHECK-NEXT: uOps Per Cycle: 4.55 +# CHECK-NEXT: IPC: 4.55 +# CHECK-NEXT: Block RThroughput: 0.3 + +# CHECK: Instruction Info: +# CHECK-NEXT: [1]: #uOps +# CHECK-NEXT: [2]: Latency +# CHECK-NEXT: [3]: RThroughput +# CHECK-NEXT: [4]: MayLoad +# CHECK-NEXT: [5]: MayStore +# CHECK-NEXT: [6]: HasSideEffects (U) + +# CHECK: [1] [2] [3] [4] [5] [6] Instructions: +# CHECK-NEXT: 1 6 0.33 * ld1 { v0.4h }, [sp] +# CHECK-NEXT: 1 2 0.25 add z0.d, z0.d, z0.d + +# CHECK: Resources: +# CHECK-NEXT: [0.0] - V2UnitB +# CHECK-NEXT: [0.1] - V2UnitB +# CHECK-NEXT: [1.0] - V2UnitD +# CHECK-NEXT: [1.1] - V2UnitD +# CHECK-NEXT: [2] - V2UnitL2 +# CHECK-NEXT: [3.0] - V2UnitL01 +# CHECK-NEXT: [3.1] - V2UnitL01 +# CHECK-NEXT: [4] - V2UnitM0 +# CHECK-NEXT: [5] - V2UnitM1 +# CHECK-NEXT: [6] - V2UnitS0 +# CHECK-NEXT: [7] - V2UnitS1 +# CHECK-NEXT: [8] - V2UnitS2 +# CHECK-NEXT: [9] - V2UnitS3 +# CHECK-NEXT: [10] - V2UnitV0 +# CHECK-NEXT: [11] - V2UnitV1 +# CHECK-NEXT: [12] - V2UnitV2 +# CHECK-NEXT: [13] - V2UnitV3 + +# CHECK: Resource pressure per iteration: +# CHECK-NEXT: [0.0] [0.1] [1.0] [1.1] [2] [3.0] [3.1] [4] [5] [6] [7] [8] [9] [10] [11] [12] [13] +# CHECK-NEXT: - - - - 0.33 0.33 0.34 - - - - - - 0.25 0.25 0.25 0.25 + +# CHECK: Resource pressure by instruction: +# CHECK-NEXT: [0.0] [0.1] [1.0] [1.1] [2] [3.0] [3.1] [4] [5] [6] [7] [8] [9] [10] [11] [12] [13] Instructions: +# CHECK-NEXT: - - - - 0.33 0.33 0.34 - - - - - - - - - - ld1 { v0.4h }, [sp] +# CHECK-NEXT: - - - - - - - - - - - - - 0.25 0.25 0.25 0.25 add z0.d, z0.d, z0.d + +# CHECK: Timeline view: +# CHECK-NEXT: 01 +# CHECK-NEXT: Index 0123456789 + +# CHECK: [0,0] DeeeeeeER .. ld1 { v0.4h }, [sp] +# CHECK-NEXT: [0,1] D======eeER. add z0.d, z0.d, z0.d +# CHECK-NEXT: [1,0] DeeeeeeE--R. ld1 { v0.4h }, [sp] +# CHECK-NEXT: [1,1] D======eeER. add z0.d, z0.d, z0.d +# CHECK-NEXT: [2,0] DeeeeeeE--R. ld1 { v0.4h }, [sp] +# CHECK-NEXT: [2,1] D======eeER. add z0.d, z0.d, z0.d +# CHECK-NEXT: [3,0] D=eeeeeeE-R. ld1 { v0.4h }, [sp] +# CHECK-NEXT: [3,1] D=======eeER add z0.d, z0.d, z0.d + +# CHECK: Average Wait times (based on the timeline view): +# CHECK-NEXT: [0]: Executions +# CHECK-NEXT: [1]: Average time spent waiting in a scheduler's queue +# CHECK-NEXT: [2]: Average time spent waiting in a scheduler's queue while ready +# CHECK-NEXT: [3]: Average time elapsed from WB until retire stage + +# CHECK: [0] [1] [2] [3] +# CHECK-NEXT: 0. 4 1.3 1.3 1.3 ld1 { v0.4h }, [sp] +# CHECK-NEXT: 1. 4 7.3 0.0 0.0 add z0.d, z0.d, z0.d +# CHECK-NEXT: 4 4.3 0.6 0.6 + +# CHECK: [7] Code Region - SIMD64-bit-s + +# CHECK: Iterations: 100 +# CHECK-NEXT: Instructions: 200 +# CHECK-NEXT: Total Cycles: 44 +# CHECK-NEXT: Total uOps: 200 + +# CHECK: Dispatch Width: 16 +# CHECK-NEXT: uOps Per Cycle: 4.55 +# CHECK-NEXT: IPC: 4.55 +# CHECK-NEXT: Block RThroughput: 0.3 + +# CHECK: Instruction Info: +# CHECK-NEXT: [1]: #uOps +# CHECK-NEXT: [2]: Latency +# CHECK-NEXT: [3]: RThroughput +# CHECK-NEXT: [4]: MayLoad +# CHECK-NEXT: [5]: MayStore +# CHECK-NEXT: [6]: HasSideEffects (U) + +# CHECK: [1] [2] [3] [4] [5] [6] Instructions: +# CHECK-NEXT: 1 6 0.33 * ld1 { v0.2s }, [sp] +# CHECK-NEXT: 1 2 0.25 add z0.d, z0.d, z0.d + +# CHECK: Resources: +# CHECK-NEXT: [0.0] - V2UnitB +# CHECK-NEXT: [0.1] - V2UnitB +# CHECK-NEXT: [1.0] - V2UnitD +# CHECK-NEXT: [1.1] - V2UnitD +# CHECK-NEXT: [2] - V2UnitL2 +# CHECK-NEXT: [3.0] - V2UnitL01 +# CHECK-NEXT: [3.1] - V2UnitL01 +# CHECK-NEXT: [4] - V2UnitM0 +# CHECK-NEXT: [5] - V2UnitM1 +# CHECK-NEXT: [6] - V2UnitS0 +# CHECK-NEXT: [7] - V2UnitS1 +# CHECK-NEXT: [8] - V2UnitS2 +# CHECK-NEXT: [9] - V2UnitS3 +# CHECK-NEXT: [10] - V2UnitV0 +# CHECK-NEXT: [11] - V2UnitV1 +# CHECK-NEXT: [12] - V2UnitV2 +# CHECK-NEXT: [13] - V2UnitV3 + +# CHECK: Resource pressure per iteration: +# CHECK-NEXT: [0.0] [0.1] [1.0] [1.1] [2] [3.0] [3.1] [4] [5] [6] [7] [8] [9] [10] [11] [12] [13] +# CHECK-NEXT: - - - - 0.33 0.33 0.34 - - - - - - 0.25 0.25 0.25 0.25 + +# CHECK: Resource pressure by instruction: +# CHECK-NEXT: [0.0] [0.1] [1.0] [1.1] [2] [3.0] [3.1] [4] [5] [6] [7] [8] [9] [10] [11] [12] [13] Instructions: +# CHECK-NEXT: - - - - 0.33 0.33 0.34 - - - - - - - - - - ld1 { v0.2s }, [sp] +# CHECK-NEXT: - - - - - - - - - - - - - 0.25 0.25 0.25 0.25 add z0.d, z0.d, z0.d + +# CHECK: Timeline view: +# CHECK-NEXT: 01 +# CHECK-NEXT: Index 0123456789 + +# CHECK: [0,0] DeeeeeeER .. ld1 { v0.2s }, [sp] +# CHECK-NEXT: [0,1] D======eeER. add z0.d, z0.d, z0.d +# CHECK-NEXT: [1,0] DeeeeeeE--R. ld1 { v0.2s }, [sp] +# CHECK-NEXT: [1,1] D======eeER. add z0.d, z0.d, z0.d +# CHECK-NEXT: [2,0] DeeeeeeE--R. ld1 { v0.2s }, [sp] +# CHECK-NEXT: [2,1] D======eeER. add z0.d, z0.d, z0.d +# CHECK-NEXT: [3,0] D=eeeeeeE-R. ld1 { v0.2s }, [sp] +# CHECK-NEXT: [3,1] D=======eeER add z0.d, z0.d, z0.d + +# CHECK: Average Wait times (based on the timeline view): +# CHECK-NEXT: [0]: Executions +# CHECK-NEXT: [1]: Average time spent waiting in a scheduler's queue +# CHECK-NEXT: [2]: Average time spent waiting in a scheduler's queue while ready +# CHECK-NEXT: [3]: Average time elapsed from WB until retire stage + +# CHECK: [0] [1] [2] [3] +# CHECK-NEXT: 0. 4 1.3 1.3 1.3 ld1 { v0.2s }, [sp] +# CHECK-NEXT: 1. 4 7.3 0.0 0.0 add z0.d, z0.d, z0.d +# CHECK-NEXT: 4 4.3 0.6 0.6 + +# CHECK: [8] Code Region - SIMD64-bit-d + +# CHECK: Iterations: 100 +# CHECK-NEXT: Instructions: 200 +# CHECK-NEXT: Total Cycles: 44 +# CHECK-NEXT: Total uOps: 200 + +# CHECK: Dispatch Width: 16 +# CHECK-NEXT: uOps Per Cycle: 4.55 +# CHECK-NEXT: IPC: 4.55 +# CHECK-NEXT: Block RThroughput: 0.3 + +# CHECK: Instruction Info: +# CHECK-NEXT: [1]: #uOps +# CHECK-NEXT: [2]: Latency +# CHECK-NEXT: [3]: RThroughput +# CHECK-NEXT: [4]: MayLoad +# CHECK-NEXT: [5]: MayStore +# CHECK-NEXT: [6]: HasSideEffects (U) + +# CHECK: [1] [2] [3] [4] [5] [6] Instructions: +# CHECK-NEXT: 1 6 0.33 * ld1 { v0.1d }, [sp] +# CHECK-NEXT: 1 2 0.25 add z0.d, z0.d, z0.d + +# CHECK: Resources: +# CHECK-NEXT: [0.0] - V2UnitB +# CHECK-NEXT: [0.1] - V2UnitB +# CHECK-NEXT: [1.0] - V2UnitD +# CHECK-NEXT: [1.1] - V2UnitD +# CHECK-NEXT: [2] - V2UnitL2 +# CHECK-NEXT: [3.0] - V2UnitL01 +# CHECK-NEXT: [3.1] - V2UnitL01 +# CHECK-NEXT: [4] - V2UnitM0 +# CHECK-NEXT: [5] - V2UnitM1 +# CHECK-NEXT: [6] - V2UnitS0 +# CHECK-NEXT: [7] - V2UnitS1 +# CHECK-NEXT: [8] - V2UnitS2 +# CHECK-NEXT: [9] - V2UnitS3 +# CHECK-NEXT: [10] - V2UnitV0 +# CHECK-NEXT: [11] - V2UnitV1 +# CHECK-NEXT: [12] - V2UnitV2 +# CHECK-NEXT: [13] - V2UnitV3 + +# CHECK: Resource pressure per iteration: +# CHECK-NEXT: [0.0] [0.1] [1.0] [1.1] [2] [3.0] [3.1] [4] [5] [6] [7] [8] [9] [10] [11] [12] [13] +# CHECK-NEXT: - - - - 0.33 0.33 0.34 - - - - - - 0.25 0.25 0.25 0.25 + +# CHECK: Resource pressure by instruction: +# CHECK-NEXT: [0.0] [0.1] [1.0] [1.1] [2] [3.0] [3.1] [4] [5] [6] [7] [8] [9] [10] [11] [12] [13] Instructions: +# CHECK-NEXT: - - - - 0.33 0.33 0.34 - - - - - - - - - - ld1 { v0.1d }, [sp] +# CHECK-NEXT: - - - - - - - - - - - - - 0.25 0.25 0.25 0.25 add z0.d, z0.d, z0.d + +# CHECK: Timeline view: +# CHECK-NEXT: 01 +# CHECK-NEXT: Index 0123456789 + +# CHECK: [0,0] DeeeeeeER .. ld1 { v0.1d }, [sp] +# CHECK-NEXT: [0,1] D======eeER. add z0.d, z0.d, z0.d +# CHECK-NEXT: [1,0] DeeeeeeE--R. ld1 { v0.1d }, [sp] +# CHECK-NEXT: [1,1] D======eeER. add z0.d, z0.d, z0.d +# CHECK-NEXT: [2,0] DeeeeeeE--R. ld1 { v0.1d }, [sp] +# CHECK-NEXT: [2,1] D======eeER. add z0.d, z0.d, z0.d +# CHECK-NEXT: [3,0] D=eeeeeeE-R. ld1 { v0.1d }, [sp] +# CHECK-NEXT: [3,1] D=======eeER add z0.d, z0.d, z0.d + +# CHECK: Average Wait times (based on the timeline view): +# CHECK-NEXT: [0]: Executions +# CHECK-NEXT: [1]: Average time spent waiting in a scheduler's queue +# CHECK-NEXT: [2]: Average time spent waiting in a scheduler's queue while ready +# CHECK-NEXT: [3]: Average time elapsed from WB until retire stage + +# CHECK: [0] [1] [2] [3] +# CHECK-NEXT: 0. 4 1.3 1.3 1.3 ld1 { v0.1d }, [sp] +# CHECK-NEXT: 1. 4 7.3 0.0 0.0 add z0.d, z0.d, z0.d +# CHECK-NEXT: 4 4.3 0.6 0.6 + +# CHECK: [9] Code Region - insr + +# CHECK: Iterations: 100 +# CHECK-NEXT: Instructions: 200 +# CHECK-NEXT: Total Cycles: 803 +# CHECK-NEXT: Total uOps: 300 + +# CHECK: Dispatch Width: 16 +# CHECK-NEXT: uOps Per Cycle: 0.37 +# CHECK-NEXT: IPC: 0.25 +# CHECK-NEXT: Block RThroughput: 1.0 + +# CHECK: Instruction Info: +# CHECK-NEXT: [1]: #uOps +# CHECK-NEXT: [2]: Latency +# CHECK-NEXT: [3]: RThroughput +# CHECK-NEXT: [4]: MayLoad +# CHECK-NEXT: [5]: MayStore +# CHECK-NEXT: [6]: HasSideEffects (U) + +# CHECK: [1] [2] [3] [4] [5] [6] Instructions: +# CHECK-NEXT: 2 6 1.00 insr z0.s, w0 +# CHECK-NEXT: 1 2 0.25 add z0.s, z0.s, z0.s + +# CHECK: Resources: +# CHECK-NEXT: [0.0] - V2UnitB +# CHECK-NEXT: [0.1] - V2UnitB +# CHECK-NEXT: [1.0] - V2UnitD +# CHECK-NEXT: [1.1] - V2UnitD +# CHECK-NEXT: [2] - V2UnitL2 +# CHECK-NEXT: [3.0] - V2UnitL01 +# CHECK-NEXT: [3.1] - V2UnitL01 +# CHECK-NEXT: [4] - V2UnitM0 +# CHECK-NEXT: [5] - V2UnitM1 +# CHECK-NEXT: [6] - V2UnitS0 +# CHECK-NEXT: [7] - V2UnitS1 +# CHECK-NEXT: [8] - V2UnitS2 +# CHECK-NEXT: [9] - V2UnitS3 +# CHECK-NEXT: [10] - V2UnitV0 +# CHECK-NEXT: [11] - V2UnitV1 +# CHECK-NEXT: [12] - V2UnitV2 +# CHECK-NEXT: [13] - V2UnitV3 + +# CHECK: Resource pressure per iteration: +# CHECK-NEXT: [0.0] [0.1] [1.0] [1.1] [2] [3.0] [3.1] [4] [5] [6] [7] [8] [9] [10] [11] [12] [13] +# CHECK-NEXT: - - - - - - - 1.00 - - - - - 0.33 1.00 0.33 0.34 + +# CHECK: Resource pressure by instruction: +# CHECK-NEXT: [0.0] [0.1] [1.0] [1.1] [2] [3.0] [3.1] [4] [5] [6] [7] [8] [9] [10] [11] [12] [13] Instructions: +# CHECK-NEXT: - - - - - - - 1.00 - - - - - - 1.00 - - insr z0.s, w0 +# CHECK-NEXT: - - - - - - - - - - - - - 0.33 - 0.33 0.34 add z0.s, z0.s, z0.s + +# CHECK: Timeline view: +# CHECK-NEXT: 0123456789 01234 +# CHECK-NEXT: Index 0123456789 0123456789 + +# CHECK: [0,0] DeeeeeeER . . . . . . insr z0.s, w0 +# CHECK-NEXT: [0,1] D======eeER . . . . . add z0.s, z0.s, z0.s +# CHECK-NEXT: [1,0] D========eeeeeeER . . . . insr z0.s, w0 +# CHECK-NEXT: [1,1] D==============eeER . . . . add z0.s, z0.s, z0.s +# CHECK-NEXT: [2,0] D================eeeeeeER. . . insr z0.s, w0 +# CHECK-NEXT: [2,1] D======================eeER . . add z0.s, z0.s, z0.s +# CHECK-NEXT: [3,0] D========================eeeeeeER . insr z0.s, w0 +# CHECK-NEXT: [3,1] D==============================eeER add z0.s, z0.s, z0.s + +# CHECK: Average Wait times (based on the timeline view): +# CHECK-NEXT: [0]: Executions +# CHECK-NEXT: [1]: Average time spent waiting in a scheduler's queue +# CHECK-NEXT: [2]: Average time spent waiting in a scheduler's queue while ready +# CHECK-NEXT: [3]: Average time elapsed from WB until retire stage + +# CHECK: [0] [1] [2] [3] +# CHECK-NEXT: 0. 4 13.0 0.3 0.0 insr z0.s, w0 +# CHECK-NEXT: 1. 4 19.0 0.0 0.0 add z0.s, z0.s, z0.s +# CHECK-NEXT: 4 16.0 0.1 0.0 -- GitLab From 7630379156ec08c9d7b1ea3c03c09e7dc89ef4ee Mon Sep 17 00:00:00 2001 From: Corentin Ferry Date: Wed, 22 May 2024 16:33:37 +0200 Subject: [PATCH 125/452] [mlir][emitc] Add EmitC lowering for arith.trunci, arith.extsi, arith.extui This commit adds conversion to EmitC for arith dialect casts between integer types (trunc, extsi, extui), excluding indexes for now. --- .../Conversion/ArithToEmitC/ArithToEmitC.cpp | 92 +++++++++++++++++++ .../arith-to-emitc-unsupported.mlir | 7 ++ .../ArithToEmitC/arith-to-emitc.mlir | 63 +++++++++++++ 3 files changed, 162 insertions(+) diff --git a/mlir/lib/Conversion/ArithToEmitC/ArithToEmitC.cpp b/mlir/lib/Conversion/ArithToEmitC/ArithToEmitC.cpp index 1447b182ccfd..0be3d76f556d 100644 --- a/mlir/lib/Conversion/ArithToEmitC/ArithToEmitC.cpp +++ b/mlir/lib/Conversion/ArithToEmitC/ArithToEmitC.cpp @@ -15,6 +15,7 @@ #include "mlir/Dialect/Arith/IR/Arith.h" #include "mlir/Dialect/EmitC/IR/EmitC.h" +#include "mlir/Tools/PDLL/AST/Types.h" #include "mlir/Transforms/DialectConversion.h" using namespace mlir; @@ -112,6 +113,93 @@ public: } }; +template +class CastConversion : public OpConversionPattern { +public: + using OpConversionPattern::OpConversionPattern; + + LogicalResult + matchAndRewrite(ArithOp op, typename ArithOp::Adaptor adaptor, + ConversionPatternRewriter &rewriter) const override { + + Type opReturnType = this->getTypeConverter()->convertType(op.getType()); + if (!isa_and_nonnull(opReturnType)) + return rewriter.notifyMatchFailure(op, "expected integer result type"); + + if (adaptor.getOperands().size() != 1) { + return rewriter.notifyMatchFailure( + op, "CastConversion only supports unary ops"); + } + + Type operandType = adaptor.getIn().getType(); + if (!isa_and_nonnull(operandType)) + return rewriter.notifyMatchFailure(op, "expected integer operand type"); + + // Signed (sign-extending) casts from i1 are not supported. + if (operandType.isInteger(1) && !castToUnsigned) + return rewriter.notifyMatchFailure(op, + "operation not supported on i1 type"); + + // to-i1 conversions: arith semantics want truncation, whereas (bool)(v) is + // equivalent to (v != 0). Implementing as (bool)(v & 0x01) gives + // truncation. + if (opReturnType.isInteger(1)) { + auto constOne = rewriter.create( + op.getLoc(), operandType, rewriter.getIntegerAttr(operandType, 1)); + auto oneAndOperand = rewriter.create( + op.getLoc(), operandType, adaptor.getIn(), constOne); + rewriter.replaceOpWithNewOp(op, opReturnType, + oneAndOperand); + return success(); + } + + bool isTruncation = operandType.getIntOrFloatBitWidth() > + opReturnType.getIntOrFloatBitWidth(); + bool doUnsigned = castToUnsigned || isTruncation; + + Type castType = opReturnType; + // If the op is a ui variant and the type wanted as + // return type isn't unsigned, we need to issue an unsigned type to do + // the conversion. + if (castType.isUnsignedInteger() != doUnsigned) { + castType = rewriter.getIntegerType(opReturnType.getIntOrFloatBitWidth(), + /*isSigned=*/!doUnsigned); + } + + Value actualOp = adaptor.getIn(); + // Adapt the signedness of the operand if necessary + if (operandType.isUnsignedInteger() != doUnsigned) { + Type correctSignednessType = + rewriter.getIntegerType(operandType.getIntOrFloatBitWidth(), + /*isSigned=*/!doUnsigned); + actualOp = rewriter.template create( + op.getLoc(), correctSignednessType, actualOp); + } + + auto result = rewriter.template create(op.getLoc(), castType, + actualOp); + + // Cast to the expected output type + if (castType != opReturnType) { + result = rewriter.template create(op.getLoc(), + opReturnType, result); + } + + rewriter.replaceOp(op, result); + return success(); + } +}; + +template +class UnsignedCastConversion : public CastConversion { + using CastConversion::CastConversion; +}; + +template +class SignedCastConversion : public CastConversion { + using CastConversion::CastConversion; +}; + template class ArithOpConversion final : public OpConversionPattern { public: @@ -313,6 +401,10 @@ void mlir::populateArithToEmitCPatterns(TypeConverter &typeConverter, IntegerOpConversion, CmpIOpConversion, SelectOpConversion, + // Truncation is guaranteed for unsigned types. + UnsignedCastConversion, + SignedCastConversion, + UnsignedCastConversion, ItoFCastOpConversion, ItoFCastOpConversion, FtoICastOpConversion, diff --git a/mlir/test/Conversion/ArithToEmitC/arith-to-emitc-unsupported.mlir b/mlir/test/Conversion/ArithToEmitC/arith-to-emitc-unsupported.mlir index 66dfa8fa3e15..97e4593f97b9 100644 --- a/mlir/test/Conversion/ArithToEmitC/arith-to-emitc-unsupported.mlir +++ b/mlir/test/Conversion/ArithToEmitC/arith-to-emitc-unsupported.mlir @@ -63,3 +63,10 @@ func.func @arith_cast_fptoui_i1(%arg0: f32) -> i1 { return %t: i1 } +// ----- + +func.func @arith_extsi_i1_to_i32(%arg0: i1) { + // expected-error @+1 {{failed to legalize operation 'arith.extsi'}} + %idx = arith.extsi %arg0 : i1 to i32 + return +} diff --git a/mlir/test/Conversion/ArithToEmitC/arith-to-emitc.mlir b/mlir/test/Conversion/ArithToEmitC/arith-to-emitc.mlir index 79fecd61494d..b453b69a214e 100644 --- a/mlir/test/Conversion/ArithToEmitC/arith-to-emitc.mlir +++ b/mlir/test/Conversion/ArithToEmitC/arith-to-emitc.mlir @@ -177,3 +177,66 @@ func.func @arith_int_to_float_cast_ops(%arg0: i8, %arg1: i64) { return } + +// ----- + +func.func @arith_trunci(%arg0: i32) -> i8 { + // CHECK-LABEL: arith_trunci + // CHECK-SAME: (%[[Arg0:[^ ]*]]: i32) + // CHECK: %[[CastUI:.*]] = emitc.cast %[[Arg0]] : i32 to ui32 + // CHECK: %[[Trunc:.*]] = emitc.cast %[[CastUI]] : ui32 to ui8 + // CHECK: emitc.cast %[[Trunc]] : ui8 to i8 + %truncd = arith.trunci %arg0 : i32 to i8 + + return %truncd : i8 +} + +// ----- + +func.func @arith_trunci_to_i1(%arg0: i32) -> i1 { + // CHECK-LABEL: arith_trunci_to_i1 + // CHECK-SAME: (%[[Arg0:[^ ]*]]: i32) + // CHECK: %[[Const:.*]] = "emitc.constant" + // CHECK-SAME: value = 1 + // CHECK: %[[And:.*]] = emitc.bitwise_and %[[Arg0]], %[[Const]] : (i32, i32) -> i32 + // CHECK: emitc.cast %[[And]] : i32 to i1 + %truncd = arith.trunci %arg0 : i32 to i1 + + return %truncd : i1 +} + +// ----- + +func.func @arith_extsi(%arg0: i32) { + // CHECK-LABEL: arith_extsi + // CHECK-SAME: ([[Arg0:[^ ]*]]: i32) + // CHECK: emitc.cast [[Arg0]] : i32 to i64 + %extd = arith.extsi %arg0 : i32 to i64 + + return +} + +// ----- + +func.func @arith_extui(%arg0: i32) { + // CHECK-LABEL: arith_extui + // CHECK-SAME: (%[[Arg0:[^ ]*]]: i32) + // CHECK: %[[Conv0:.*]] = emitc.cast %[[Arg0]] : i32 to ui32 + // CHECK: %[[Conv1:.*]] = emitc.cast %[[Conv0]] : ui32 to ui64 + // CHECK: emitc.cast %[[Conv1]] : ui64 to i64 + %extd = arith.extui %arg0 : i32 to i64 + + return +} + +// ----- + +func.func @arith_extui_i1_to_i32(%arg0: i1) { + // CHECK-LABEL: arith_extui_i1_to_i32 + // CHECK-SAME: (%[[Arg0:[^ ]*]]: i1) + // CHECK: %[[Conv0:.*]] = emitc.cast %[[Arg0]] : i1 to ui1 + // CHECK: %[[Conv1:.*]] = emitc.cast %[[Conv0]] : ui1 to ui32 + // CHECK: emitc.cast %[[Conv1]] : ui32 to i32 + %idx = arith.extui %arg0 : i1 to i32 + return +} -- GitLab From 183beb33d7f8847c04870e425d75f27db1cf5847 Mon Sep 17 00:00:00 2001 From: Alexey Karyakin Date: Wed, 22 May 2024 09:38:44 -0500 Subject: [PATCH 126/452] [llvm-objcopy] Check for missing argument values (#70710) Report an error if a required value for a command line argument is missing. --- llvm/test/tools/llvm-objcopy/tool-options.test | 6 ++++++ llvm/tools/llvm-objcopy/ObjcopyOptions.cpp | 6 ++++++ 2 files changed, 12 insertions(+) create mode 100644 llvm/test/tools/llvm-objcopy/tool-options.test diff --git a/llvm/test/tools/llvm-objcopy/tool-options.test b/llvm/test/tools/llvm-objcopy/tool-options.test new file mode 100644 index 000000000000..8d2bb4476009 --- /dev/null +++ b/llvm/test/tools/llvm-objcopy/tool-options.test @@ -0,0 +1,6 @@ +## An error must be reported if a required argument value is missing. +# RUN: not llvm-objcopy --only-section 2>&1 | FileCheck --check-prefix=CHECK-NO-VALUE-ONLY-SECTION %s +# CHECK-NO-VALUE-ONLY-SECTION: error: argument to '--only-section' is missing (expected 1 value(s)) + +# RUN: not llvm-objcopy -O 2>&1 | FileCheck --check-prefix=CHECK-NO-VALUE-O %s +# CHECK-NO-VALUE-O: error: argument to '-O' is missing (expected 1 value(s)) diff --git a/llvm/tools/llvm-objcopy/ObjcopyOptions.cpp b/llvm/tools/llvm-objcopy/ObjcopyOptions.cpp index a1897334cff2..4ab3b7265f2f 100644 --- a/llvm/tools/llvm-objcopy/ObjcopyOptions.cpp +++ b/llvm/tools/llvm-objcopy/ObjcopyOptions.cpp @@ -571,6 +571,12 @@ objcopy::parseObjcopyOptions(ArrayRef RawArgsArr, llvm::opt::InputArgList InputArgs = T.ParseArgs(ArgsArr, MissingArgumentIndex, MissingArgumentCount); + if (MissingArgumentCount) + return createStringError( + errc::invalid_argument, + "argument to '%s' is missing (expected %d value(s))", + InputArgs.getArgString(MissingArgumentIndex), MissingArgumentCount); + if (InputArgs.size() == 0 && DashDash == RawArgsArr.end()) { printHelp(T, errs(), ToolType::Objcopy); exit(1); -- GitLab From 831d1435193e73026e03e006a5b86591f3d202b3 Mon Sep 17 00:00:00 2001 From: Ye Luo Date: Wed, 22 May 2024 09:40:43 -0500 Subject: [PATCH 127/452] [Offload] libomptarget force dlopen vendor libraries by default. (#92788) Since #87009, libomptarget directly links all the plugins statically. All the dependencies of plugins got exposed to libomptarget. The CUDA plugin depends on libcuda and the amdgpu plugin depends on libhsa if not forced using dlopen. On a cluster with different compute node architectures, libomptarget can be built and run on different nodes. In the build stage, if cmake founds libcuda and `LIBOMPTARGET_FORCE_DLOPEN_LIBCUDA=OFF`, libomptarget links libcuda.so directly and the result libomptarget may not run a node without a NVIDIA driver for example a CPU or AMD GPU only machine with a complaint that libcuda.so not found. The solution is setting `LIBOMPTARGET_FORCE_DLOPEN_LIBCUDA` and `LIBOMPTARGET_FORCE_DLOPEN_LIBHSA` `ON`. Preferably this should be default to maximize the usability of libomptarget. If cmake detects NVIDIA or AMD software on an OS imaging building node, the resulted libomptarget may not be able to function on the user side due to the requirement the existence of vendor runtime libraries. --- offload/plugins-nextgen/amdgpu/CMakeLists.txt | 2 +- offload/plugins-nextgen/cuda/CMakeLists.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/offload/plugins-nextgen/amdgpu/CMakeLists.txt b/offload/plugins-nextgen/amdgpu/CMakeLists.txt index 2f4057c0ae7e..7630e3788dae 100644 --- a/offload/plugins-nextgen/amdgpu/CMakeLists.txt +++ b/offload/plugins-nextgen/amdgpu/CMakeLists.txt @@ -13,7 +13,7 @@ target_sources(omptarget.rtl.amdgpu PRIVATE src/rtl.cpp) target_include_directories(omptarget.rtl.amdgpu PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/utils) -option(LIBOMPTARGET_FORCE_DLOPEN_LIBHSA "Build with dlopened libhsa" OFF) +option(LIBOMPTARGET_FORCE_DLOPEN_LIBHSA "Build with dlopened libhsa" ON) if(hsa-runtime64_FOUND AND NOT LIBOMPTARGET_FORCE_DLOPEN_LIBHSA) message(STATUS "Building AMDGPU plugin linked against libhsa") target_link_libraries(omptarget.rtl.amdgpu PRIVATE hsa-runtime64::hsa-runtime64) diff --git a/offload/plugins-nextgen/cuda/CMakeLists.txt b/offload/plugins-nextgen/cuda/CMakeLists.txt index 10ff612848ad..fa5559c5e7dc 100644 --- a/offload/plugins-nextgen/cuda/CMakeLists.txt +++ b/offload/plugins-nextgen/cuda/CMakeLists.txt @@ -10,7 +10,7 @@ add_target_library(omptarget.rtl.cuda CUDA) target_sources(omptarget.rtl.cuda PRIVATE src/rtl.cpp) -option(LIBOMPTARGET_FORCE_DLOPEN_LIBCUDA "Build with dlopened libcuda" OFF) +option(LIBOMPTARGET_FORCE_DLOPEN_LIBCUDA "Build with dlopened libcuda" ON) if(LIBOMPTARGET_DEP_CUDA_FOUND AND NOT LIBOMPTARGET_FORCE_DLOPEN_LIBCUDA) message(STATUS "Building CUDA plugin linked against libcuda") target_link_libraries(omptarget.rtl.cuda PRIVATE CUDA::cuda_driver) -- GitLab From c8dc6b59d68635f73d2970b7fc8bc9c6c2684098 Mon Sep 17 00:00:00 2001 From: Yingwei Zheng Date: Wed, 22 May 2024 22:43:10 +0800 Subject: [PATCH 128/452] [SDAG] Improve `SimplifyDemandedBits` for mul (#90034) If the RHS is a constant with X trailing zeros, then the X MSBs of the LHS are not demanded. Alive2: https://alive2.llvm.org/ce/z/F5CyJW Fixes https://github.com/llvm/llvm-project/issues/56645. --- .../CodeGen/SelectionDAG/TargetLowering.cpp | 12 +- llvm/test/CodeGen/AArch64/neon-dotreduce.ll | 536 +++++++++--------- llvm/test/CodeGen/RISCV/mul.ll | 149 +++++ .../CodeGen/RISCV/rv64-legal-i32/rv64zba.ll | 12 +- llvm/test/CodeGen/RISCV/rv64zba.ll | 12 +- llvm/test/CodeGen/RISCV/sextw-removal.ll | 19 +- llvm/test/CodeGen/Thumb2/mve-vecreduce-add.ll | 124 ++-- llvm/test/CodeGen/X86/combine-srem.ll | 4 +- llvm/test/CodeGen/X86/pmul.ll | 11 +- llvm/test/CodeGen/X86/shrink_vmul.ll | 4 +- 10 files changed, 513 insertions(+), 370 deletions(-) diff --git a/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp b/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp index 87c4c62522c1..85bd45a88542 100644 --- a/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp @@ -2814,10 +2814,16 @@ bool TargetLowering::SimplifyDemandedBits( unsigned DemandedBitsLZ = DemandedBits.countl_zero(); APInt LoMask = APInt::getLowBitsSet(BitWidth, BitWidth - DemandedBitsLZ); KnownBits KnownOp0, KnownOp1; - if (SimplifyDemandedBits(Op0, LoMask, DemandedElts, KnownOp0, TLO, - Depth + 1) || - SimplifyDemandedBits(Op1, LoMask, DemandedElts, KnownOp1, TLO, + auto GetDemandedBitsLHSMask = [&](APInt Demanded, + const KnownBits &KnownRHS) { + if (Op.getOpcode() == ISD::MUL) + Demanded.clearHighBits(KnownRHS.countMinTrailingZeros()); + return Demanded; + }; + if (SimplifyDemandedBits(Op1, LoMask, DemandedElts, KnownOp1, TLO, Depth + 1) || + SimplifyDemandedBits(Op0, GetDemandedBitsLHSMask(LoMask, KnownOp1), + DemandedElts, KnownOp0, TLO, Depth + 1) || // See if the operation should be performed at a smaller bit width. ShrinkDemandedOp(Op, BitWidth, DemandedBits, TLO)) { if (Flags.hasNoSignedWrap() || Flags.hasNoUnsignedWrap()) { diff --git a/llvm/test/CodeGen/AArch64/neon-dotreduce.ll b/llvm/test/CodeGen/AArch64/neon-dotreduce.ll index 736f66c935e7..40b8a47f92aa 100644 --- a/llvm/test/CodeGen/AArch64/neon-dotreduce.ll +++ b/llvm/test/CodeGen/AArch64/neon-dotreduce.ll @@ -1709,289 +1709,289 @@ define i32 @test_sdot_v33i8_double(<33 x i8> %a, <33 x i8> %b, <33 x i8> %c, <33 ; CHECK-NEXT: str x29, [sp, #-16]! // 8-byte Folded Spill ; CHECK-NEXT: .cfi_def_cfa_offset 16 ; CHECK-NEXT: .cfi_offset w29, -16 +; CHECK-NEXT: fmov s4, w0 ; CHECK-NEXT: ldr b0, [sp, #80] ; CHECK-NEXT: add x8, sp, #88 -; CHECK-NEXT: ldr b2, [sp, #144] -; CHECK-NEXT: fmov s4, w0 +; CHECK-NEXT: ldr b1, [sp, #144] ; CHECK-NEXT: add x10, sp, #152 -; CHECK-NEXT: ldr b3, [sp, #16] +; CHECK-NEXT: ldr b6, [sp, #16] ; CHECK-NEXT: ld1 { v0.b }[1], [x8] -; CHECK-NEXT: ld1 { v2.b }[1], [x10] -; CHECK-NEXT: add x10, sp, #24 -; CHECK-NEXT: ldr b1, [sp, #344] ; CHECK-NEXT: add x9, sp, #96 -; CHECK-NEXT: ld1 { v3.b }[1], [x10] -; CHECK-NEXT: add x10, sp, #352 +; CHECK-NEXT: ldr b2, [sp, #344] ; CHECK-NEXT: mov v4.b[1], w1 +; CHECK-NEXT: ld1 { v1.b }[1], [x10] +; CHECK-NEXT: add x10, sp, #24 +; CHECK-NEXT: ld1 { v6.b }[1], [x10] +; CHECK-NEXT: add x10, sp, #352 ; CHECK-NEXT: add x8, sp, #104 ; CHECK-NEXT: ld1 { v0.b }[2], [x9] ; CHECK-NEXT: add x9, sp, #160 -; CHECK-NEXT: ld1 { v1.b }[1], [x10] -; CHECK-NEXT: ld1 { v2.b }[2], [x9] -; CHECK-NEXT: add x9, sp, #32 -; CHECK-NEXT: add x12, sp, #360 -; CHECK-NEXT: ld1 { v3.b }[2], [x9] +; CHECK-NEXT: ld1 { v2.b }[1], [x10] +; CHECK-NEXT: ld1 { v1.b }[2], [x9] +; CHECK-NEXT: add x10, sp, #32 ; CHECK-NEXT: add x11, sp, #112 -; CHECK-NEXT: add x10, sp, #120 -; CHECK-NEXT: ld1 { v1.b }[2], [x12] -; CHECK-NEXT: add x12, sp, #168 -; CHECK-NEXT: ld1 { v0.b }[3], [x8] ; CHECK-NEXT: mov v4.b[2], w2 -; CHECK-NEXT: ld1 { v2.b }[3], [x12] -; CHECK-NEXT: add x12, sp, #40 -; CHECK-NEXT: ld1 { v3.b }[3], [x12] -; CHECK-NEXT: add x13, sp, #176 -; CHECK-NEXT: ldr b16, [sp, #216] -; CHECK-NEXT: ld1 { v0.b }[4], [x11] -; CHECK-NEXT: add x11, sp, #48 -; CHECK-NEXT: add x12, sp, #368 -; CHECK-NEXT: ld1 { v2.b }[4], [x13] +; CHECK-NEXT: ld1 { v6.b }[2], [x10] +; CHECK-NEXT: add x10, sp, #168 +; CHECK-NEXT: ld1 { v0.b }[3], [x8] +; CHECK-NEXT: ldr b5, [sp, #216] ; CHECK-NEXT: add x13, sp, #224 -; CHECK-NEXT: add x9, sp, #128 +; CHECK-NEXT: ld1 { v1.b }[3], [x10] +; CHECK-NEXT: add x10, sp, #40 +; CHECK-NEXT: add x12, sp, #120 +; CHECK-NEXT: ld1 { v6.b }[3], [x10] +; CHECK-NEXT: add x10, sp, #176 +; CHECK-NEXT: ld1 { v5.b }[1], [x13] ; CHECK-NEXT: mov v4.b[3], w3 -; CHECK-NEXT: ld1 { v3.b }[4], [x11] -; CHECK-NEXT: ld1 { v16.b }[1], [x13] -; CHECK-NEXT: ld1 { v0.b }[5], [x10] -; CHECK-NEXT: add x10, sp, #56 -; CHECK-NEXT: ld1 { v1.b }[3], [x12] -; CHECK-NEXT: add x12, sp, #184 -; CHECK-NEXT: ldr b5, [sp, #280] -; CHECK-NEXT: add x11, sp, #376 -; CHECK-NEXT: ld1 { v3.b }[5], [x10] -; CHECK-NEXT: ld1 { v2.b }[5], [x12] -; CHECK-NEXT: add x10, sp, #232 +; CHECK-NEXT: ld1 { v0.b }[4], [x11] +; CHECK-NEXT: add x11, sp, #48 +; CHECK-NEXT: add x8, sp, #360 +; CHECK-NEXT: ld1 { v1.b }[4], [x10] +; CHECK-NEXT: add x13, sp, #56 +; CHECK-NEXT: ld1 { v6.b }[4], [x11] +; CHECK-NEXT: ldr b7, [sp, #280] +; CHECK-NEXT: ld1 { v2.b }[2], [x8] +; CHECK-NEXT: add x15, sp, #232 +; CHECK-NEXT: ld1 { v0.b }[5], [x12] +; CHECK-NEXT: add x14, sp, #184 ; CHECK-NEXT: mov v4.b[4], w4 +; CHECK-NEXT: ld1 { v5.b }[2], [x15] +; CHECK-NEXT: add x9, sp, #128 +; CHECK-NEXT: ld1 { v6.b }[5], [x13] +; CHECK-NEXT: add x13, sp, #288 +; CHECK-NEXT: add x10, sp, #368 +; CHECK-NEXT: ld1 { v7.b }[1], [x13] +; CHECK-NEXT: ld1 { v1.b }[5], [x14] +; CHECK-NEXT: ld1 { v2.b }[3], [x10] +; CHECK-NEXT: add x15, sp, #240 ; CHECK-NEXT: ld1 { v0.b }[6], [x9] -; CHECK-NEXT: add x9, sp, #288 -; CHECK-NEXT: add x15, sp, #64 -; CHECK-NEXT: ld1 { v16.b }[2], [x10] -; CHECK-NEXT: ldr b17, [sp, #408] -; CHECK-NEXT: ld1 { v5.b }[1], [x9] -; CHECK-NEXT: add x14, sp, #192 -; CHECK-NEXT: ld1 { v1.b }[4], [x11] -; CHECK-NEXT: ld1 { v3.b }[6], [x15] -; CHECK-NEXT: add x15, sp, #416 -; CHECK-NEXT: ld1 { v2.b }[6], [x14] -; CHECK-NEXT: add x14, sp, #240 -; CHECK-NEXT: ld1 { v17.b }[1], [x15] ; CHECK-NEXT: add x9, sp, #296 -; CHECK-NEXT: add x8, sp, #136 ; CHECK-NEXT: mov v4.b[5], w5 -; CHECK-NEXT: add x13, sp, #384 -; CHECK-NEXT: ld1 { v16.b }[3], [x14] -; CHECK-NEXT: ld1 { v5.b }[2], [x9] -; CHECK-NEXT: ld1 { v1.b }[5], [x13] -; CHECK-NEXT: ld1 { v0.b }[7], [x8] -; CHECK-NEXT: add x8, sp, #424 -; CHECK-NEXT: add x9, sp, #248 -; CHECK-NEXT: ld1 { v17.b }[2], [x8] -; CHECK-NEXT: add x8, sp, #304 -; CHECK-NEXT: add x10, sp, #392 -; CHECK-NEXT: ld1 { v16.b }[4], [x9] -; CHECK-NEXT: ld1 { v5.b }[3], [x8] +; CHECK-NEXT: add x11, sp, #192 +; CHECK-NEXT: ld1 { v5.b }[3], [x15] +; CHECK-NEXT: ldr b3, [sp, #408] +; CHECK-NEXT: ld1 { v7.b }[2], [x9] +; CHECK-NEXT: add x12, sp, #64 +; CHECK-NEXT: add x13, sp, #376 +; CHECK-NEXT: ld1 { v1.b }[6], [x11] +; CHECK-NEXT: add x11, sp, #416 +; CHECK-NEXT: ld1 { v6.b }[6], [x12] +; CHECK-NEXT: add x12, sp, #248 +; CHECK-NEXT: ld1 { v3.b }[1], [x11] ; CHECK-NEXT: mov v4.b[6], w6 -; CHECK-NEXT: ld1 { v1.b }[6], [x10] -; CHECK-NEXT: add x10, sp, #432 -; CHECK-NEXT: add x9, sp, #256 -; CHECK-NEXT: ld1 { v17.b }[3], [x10] -; CHECK-NEXT: add x10, sp, #312 -; CHECK-NEXT: ldr b22, [sp, #608] -; CHECK-NEXT: add x8, sp, #400 -; CHECK-NEXT: ld1 { v16.b }[5], [x9] -; CHECK-NEXT: ld1 { v5.b }[4], [x10] -; CHECK-NEXT: add x9, sp, #616 -; CHECK-NEXT: ld1 { v1.b }[7], [x8] -; CHECK-NEXT: add x8, sp, #440 -; CHECK-NEXT: ld1 { v22.b }[1], [x9] +; CHECK-NEXT: ld1 { v2.b }[4], [x13] +; CHECK-NEXT: add x11, sp, #304 +; CHECK-NEXT: ld1 { v5.b }[4], [x12] +; CHECK-NEXT: ld1 { v7.b }[3], [x11] +; CHECK-NEXT: add x8, sp, #136 +; CHECK-NEXT: add x15, sp, #384 +; CHECK-NEXT: add x9, sp, #424 +; CHECK-NEXT: ld1 { v0.b }[7], [x8] +; CHECK-NEXT: ld1 { v3.b }[2], [x9] +; CHECK-NEXT: ld1 { v2.b }[5], [x15] +; CHECK-NEXT: add x8, sp, #312 ; CHECK-NEXT: mov v4.b[7], w7 -; CHECK-NEXT: ld1 { v17.b }[4], [x8] +; CHECK-NEXT: add x9, sp, #256 +; CHECK-NEXT: add x10, sp, #200 +; CHECK-NEXT: ld1 { v7.b }[4], [x8] +; CHECK-NEXT: ld1 { v5.b }[5], [x9] +; CHECK-NEXT: add x14, sp, #72 +; CHECK-NEXT: ld1 { v1.b }[7], [x10] +; CHECK-NEXT: add x10, sp, #432 +; CHECK-NEXT: add x8, sp, #392 +; CHECK-NEXT: ld1 { v6.b }[7], [x14] +; CHECK-NEXT: ld1 { v3.b }[3], [x10] +; CHECK-NEXT: ld1 { v2.b }[6], [x8] ; CHECK-NEXT: add x8, sp, #320 +; CHECK-NEXT: add x9, sp, #264 +; CHECK-NEXT: sshll v21.8h, v4.8b, #0 +; CHECK-NEXT: ldr b4, [sp, #208] +; CHECK-NEXT: ld1 { v7.b }[5], [x8] +; CHECK-NEXT: ld1 { v5.b }[6], [x9] +; CHECK-NEXT: add x10, sp, #440 +; CHECK-NEXT: add x8, sp, #400 +; CHECK-NEXT: sshll v16.8h, v6.8b, #0 +; CHECK-NEXT: sshll v6.8h, v4.8b, #0 +; CHECK-NEXT: ld1 { v3.b }[4], [x10] +; CHECK-NEXT: ld1 { v2.b }[7], [x8] +; CHECK-NEXT: add x8, sp, #272 +; CHECK-NEXT: add x9, sp, #328 +; CHECK-NEXT: ldr b4, [sp, #608] +; CHECK-NEXT: ld1 { v7.b }[6], [x9] +; CHECK-NEXT: ld1 { v5.b }[7], [x8] +; CHECK-NEXT: add x8, sp, #616 ; CHECK-NEXT: add x10, sp, #448 -; CHECK-NEXT: ldr b6, [sp, #208] -; CHECK-NEXT: ld1 { v5.b }[5], [x8] -; CHECK-NEXT: add x8, sp, #624 -; CHECK-NEXT: ldr b7, [sp, #472] -; CHECK-NEXT: ld1 { v22.b }[2], [x8] -; CHECK-NEXT: ld1 { v17.b }[5], [x10] -; CHECK-NEXT: add x10, sp, #328 -; CHECK-NEXT: sshll v20.8h, v4.8b, #0 -; CHECK-NEXT: ldr b4, [sp, #480] +; CHECK-NEXT: ld1 { v4.b }[1], [x8] +; CHECK-NEXT: ldr b18, [sp, #480] +; CHECK-NEXT: ld1 { v3.b }[5], [x10] +; CHECK-NEXT: add x9, sp, #336 +; CHECK-NEXT: ldr b17, [sp, #472] +; CHECK-NEXT: add x8, sp, #488 +; CHECK-NEXT: ld1 { v7.b }[7], [x9] +; CHECK-NEXT: add x9, sp, #624 +; CHECK-NEXT: ld1 { v18.b }[1], [x8] +; CHECK-NEXT: sshll v22.8h, v5.8b, #0 ; CHECK-NEXT: add x8, sp, #456 -; CHECK-NEXT: ld1 { v5.b }[6], [x10] -; CHECK-NEXT: add x10, sp, #632 -; CHECK-NEXT: sshll v6.8h, v6.8b, #0 -; CHECK-NEXT: ld1 { v22.b }[3], [x10] -; CHECK-NEXT: add x10, sp, #488 -; CHECK-NEXT: ld1 { v17.b }[6], [x8] -; CHECK-NEXT: add x8, sp, #336 -; CHECK-NEXT: ld1 { v4.b }[1], [x10] -; CHECK-NEXT: sshll v7.8h, v7.8b, #0 -; CHECK-NEXT: ld1 { v5.b }[7], [x8] -; CHECK-NEXT: add x8, sp, #640 -; CHECK-NEXT: add x9, sp, #264 -; CHECK-NEXT: ld1 { v22.b }[4], [x8] +; CHECK-NEXT: sshll v5.8h, v17.8b, #0 +; CHECK-NEXT: ld1 { v4.b }[2], [x9] +; CHECK-NEXT: ld1 { v3.b }[6], [x8] ; CHECK-NEXT: add x8, sp, #496 -; CHECK-NEXT: ld1 { v16.b }[6], [x9] -; CHECK-NEXT: ld1 { v4.b }[2], [x8] -; CHECK-NEXT: add x8, sp, #648 -; CHECK-NEXT: smull v18.4s, v6.4h, v7.4h -; CHECK-NEXT: ldr b7, [sp, #544] -; CHECK-NEXT: add x9, sp, #272 -; CHECK-NEXT: movi v6.2d, #0000000000000000 -; CHECK-NEXT: ld1 { v22.b }[5], [x8] +; CHECK-NEXT: sshll v17.8h, v7.8b, #0 +; CHECK-NEXT: add x10, sp, #632 +; CHECK-NEXT: ld1 { v18.b }[2], [x8] +; CHECK-NEXT: add x9, sp, #464 ; CHECK-NEXT: add x8, sp, #504 -; CHECK-NEXT: ld1 { v16.b }[7], [x9] -; CHECK-NEXT: ld1 { v4.b }[3], [x8] -; CHECK-NEXT: add x8, sp, #552 -; CHECK-NEXT: add x9, sp, #656 -; CHECK-NEXT: ld1 { v7.b }[1], [x8] +; CHECK-NEXT: smull v19.4s, v6.4h, v5.4h +; CHECK-NEXT: movi v5.2d, #0000000000000000 +; CHECK-NEXT: ld1 { v4.b }[3], [x10] +; CHECK-NEXT: ld1 { v3.b }[7], [x9] +; CHECK-NEXT: smull v6.4s, v16.4h, v17.4h +; CHECK-NEXT: add x9, sp, #640 +; CHECK-NEXT: ld1 { v18.b }[3], [x8] +; CHECK-NEXT: smull2 v16.4s, v16.8h, v17.8h +; CHECK-NEXT: ldr b17, [sp, #672] +; CHECK-NEXT: ld1 { v4.b }[4], [x9] +; CHECK-NEXT: add x9, sp, #680 +; CHECK-NEXT: ldr b20, [sp, #544] +; CHECK-NEXT: mov v5.s[0], v19.s[0] ; CHECK-NEXT: add x8, sp, #512 -; CHECK-NEXT: ldr b21, [sp, #672] -; CHECK-NEXT: ld1 { v22.b }[6], [x9] -; CHECK-NEXT: mov v6.s[0], v18.s[0] -; CHECK-NEXT: add x9, sp, #664 -; CHECK-NEXT: ld1 { v4.b }[4], [x8] -; CHECK-NEXT: add x8, sp, #560 -; CHECK-NEXT: sshll v23.8h, v16.8b, #0 -; CHECK-NEXT: ld1 { v7.b }[2], [x8] -; CHECK-NEXT: add x8, sp, #520 -; CHECK-NEXT: movi v19.2d, #0000000000000000 -; CHECK-NEXT: ld1 { v22.b }[7], [x9] -; CHECK-NEXT: add x9, sp, #528 -; CHECK-NEXT: add x10, sp, #464 -; CHECK-NEXT: ld1 { v4.b }[5], [x8] -; CHECK-NEXT: add x8, sp, #568 -; CHECK-NEXT: smull2 v18.4s, v20.8h, v23.8h -; CHECK-NEXT: ld1 { v7.b }[3], [x8] -; CHECK-NEXT: add x8, sp, #680 -; CHECK-NEXT: smlal v6.4s, v20.4h, v23.4h -; CHECK-NEXT: ld1 { v21.b }[1], [x8] -; CHECK-NEXT: sshll v20.8h, v22.8b, #0 -; CHECK-NEXT: ldr b22, [sp, #736] -; CHECK-NEXT: ld1 { v4.b }[6], [x9] -; CHECK-NEXT: add x9, sp, #576 -; CHECK-NEXT: ldr b23, [sp, #1000] -; CHECK-NEXT: ld1 { v7.b }[4], [x9] -; CHECK-NEXT: add x9, sp, #688 -; CHECK-NEXT: sshll v24.8h, v22.8b, #0 -; CHECK-NEXT: ld1 { v21.b }[2], [x9] +; CHECK-NEXT: ld1 { v17.b }[1], [x9] +; CHECK-NEXT: add x11, sp, #552 +; CHECK-NEXT: add x10, sp, #648 +; CHECK-NEXT: ld1 { v18.b }[4], [x8] +; CHECK-NEXT: ld1 { v20.b }[1], [x11] +; CHECK-NEXT: ld1 { v4.b }[5], [x10] +; CHECK-NEXT: add x10, sp, #688 +; CHECK-NEXT: add x9, sp, #520 +; CHECK-NEXT: ld1 { v17.b }[2], [x10] +; CHECK-NEXT: add x10, sp, #560 +; CHECK-NEXT: smull2 v7.4s, v21.8h, v22.8h +; CHECK-NEXT: ld1 { v18.b }[5], [x9] +; CHECK-NEXT: smlal v5.4s, v21.4h, v22.4h +; CHECK-NEXT: ld1 { v20.b }[2], [x10] +; CHECK-NEXT: ldr b21, [sp, #736] +; CHECK-NEXT: ldr b22, [sp, #1000] +; CHECK-NEXT: add x8, sp, #656 ; CHECK-NEXT: add x9, sp, #696 -; CHECK-NEXT: sshll v25.8h, v23.8b, #0 -; CHECK-NEXT: add x8, sp, #536 -; CHECK-NEXT: ldr b22, [sp, #872] -; CHECK-NEXT: ldr b23, [sp, #936] -; CHECK-NEXT: ld1 { v4.b }[7], [x8] -; CHECK-NEXT: add x8, sp, #584 -; CHECK-NEXT: ld1 { v17.b }[7], [x10] -; CHECK-NEXT: ld1 { v21.b }[3], [x9] -; CHECK-NEXT: ld1 { v7.b }[5], [x8] -; CHECK-NEXT: add x8, sp, #880 -; CHECK-NEXT: add x9, sp, #704 -; CHECK-NEXT: smull v25.4s, v24.4h, v25.4h -; CHECK-NEXT: ldr b24, [sp, #744] -; CHECK-NEXT: ld1 { v22.b }[1], [x8] -; CHECK-NEXT: add x8, sp, #944 -; CHECK-NEXT: add x10, sp, #888 -; CHECK-NEXT: ld1 { v21.b }[4], [x9] -; CHECK-NEXT: add x9, sp, #752 -; CHECK-NEXT: ld1 { v23.b }[1], [x8] -; CHECK-NEXT: ld1 { v24.b }[1], [x9] -; CHECK-NEXT: add x8, sp, #712 +; CHECK-NEXT: add x11, sp, #568 +; CHECK-NEXT: ld1 { v4.b }[6], [x8] +; CHECK-NEXT: add x8, sp, #528 +; CHECK-NEXT: ld1 { v17.b }[3], [x9] +; CHECK-NEXT: sshll v21.8h, v21.8b, #0 +; CHECK-NEXT: sshll v24.8h, v22.8b, #0 +; CHECK-NEXT: ld1 { v18.b }[6], [x8] +; CHECK-NEXT: ld1 { v20.b }[3], [x11] +; CHECK-NEXT: add x10, sp, #704 +; CHECK-NEXT: ldr b23, [sp, #808] +; CHECK-NEXT: movi v19.2d, #0000000000000000 +; CHECK-NEXT: add x9, sp, #536 +; CHECK-NEXT: ld1 { v17.b }[4], [x10] +; CHECK-NEXT: add x10, sp, #576 +; CHECK-NEXT: ldr b22, [sp, #744] +; CHECK-NEXT: add x11, sp, #816 +; CHECK-NEXT: smull v24.4s, v21.4h, v24.4h +; CHECK-NEXT: ld1 { v18.b }[7], [x9] +; CHECK-NEXT: ld1 { v20.b }[4], [x10] +; CHECK-NEXT: add x10, sp, #752 +; CHECK-NEXT: ld1 { v23.b }[1], [x11] +; CHECK-NEXT: add x9, sp, #712 +; CHECK-NEXT: ld1 { v22.b }[1], [x10] +; CHECK-NEXT: ld1 { v17.b }[5], [x9] +; CHECK-NEXT: add x9, sp, #584 +; CHECK-NEXT: add x10, sp, #824 +; CHECK-NEXT: sshll v21.8h, v18.8b, #0 +; CHECK-NEXT: ld1 { v20.b }[5], [x9] ; CHECK-NEXT: add x9, sp, #760 -; CHECK-NEXT: ld1 { v22.b }[2], [x10] -; CHECK-NEXT: add x10, sp, #952 -; CHECK-NEXT: mov v19.s[0], v25.s[0] -; CHECK-NEXT: ldr b25, [sp, #808] +; CHECK-NEXT: ldr b18, [sp, #936] ; CHECK-NEXT: ld1 { v23.b }[2], [x10] -; CHECK-NEXT: ld1 { v21.b }[5], [x8] -; CHECK-NEXT: ld1 { v24.b }[2], [x9] -; CHECK-NEXT: add x8, sp, #816 -; CHECK-NEXT: add x9, sp, #896 -; CHECK-NEXT: ld1 { v25.b }[1], [x8] -; CHECK-NEXT: add x8, sp, #960 -; CHECK-NEXT: ld1 { v22.b }[3], [x9] -; CHECK-NEXT: add x9, sp, #768 -; CHECK-NEXT: ld1 { v23.b }[3], [x8] -; CHECK-NEXT: add x10, sp, #904 -; CHECK-NEXT: ld1 { v24.b }[3], [x9] -; CHECK-NEXT: add x9, sp, #824 -; CHECK-NEXT: add x8, sp, #720 -; CHECK-NEXT: ld1 { v25.b }[2], [x9] -; CHECK-NEXT: add x9, sp, #968 -; CHECK-NEXT: ld1 { v22.b }[4], [x10] -; CHECK-NEXT: add x10, sp, #776 -; CHECK-NEXT: ld1 { v23.b }[4], [x9] -; CHECK-NEXT: ld1 { v21.b }[6], [x8] -; CHECK-NEXT: ld1 { v24.b }[4], [x10] -; CHECK-NEXT: add x8, sp, #832 -; CHECK-NEXT: add x9, sp, #912 -; CHECK-NEXT: ld1 { v25.b }[3], [x8] -; CHECK-NEXT: add x8, sp, #976 -; CHECK-NEXT: ld1 { v22.b }[5], [x9] -; CHECK-NEXT: add x9, sp, #784 -; CHECK-NEXT: ld1 { v23.b }[5], [x8] -; CHECK-NEXT: add x10, sp, #920 -; CHECK-NEXT: ld1 { v24.b }[5], [x9] -; CHECK-NEXT: add x9, sp, #840 -; CHECK-NEXT: add x8, sp, #728 -; CHECK-NEXT: ld1 { v25.b }[4], [x9] -; CHECK-NEXT: add x9, sp, #984 -; CHECK-NEXT: ld1 { v22.b }[6], [x10] -; CHECK-NEXT: add x10, sp, #792 -; CHECK-NEXT: ld1 { v23.b }[6], [x9] -; CHECK-NEXT: ld1 { v21.b }[7], [x8] -; CHECK-NEXT: ld1 { v24.b }[6], [x10] -; CHECK-NEXT: add x8, sp, #848 -; CHECK-NEXT: add x9, sp, #928 -; CHECK-NEXT: ld1 { v25.b }[5], [x8] -; CHECK-NEXT: add x12, sp, #72 -; CHECK-NEXT: add x8, sp, #992 -; CHECK-NEXT: ld1 { v22.b }[7], [x9] -; CHECK-NEXT: add x9, sp, #800 -; CHECK-NEXT: ld1 { v3.b }[7], [x12] -; CHECK-NEXT: ld1 { v23.b }[7], [x8] -; CHECK-NEXT: add x8, sp, #592 -; CHECK-NEXT: ld1 { v24.b }[7], [x9] -; CHECK-NEXT: add x9, sp, #856 -; CHECK-NEXT: ld1 { v7.b }[6], [x8] -; CHECK-NEXT: add x11, sp, #200 -; CHECK-NEXT: ld1 { v25.b }[6], [x9] -; CHECK-NEXT: sshll v3.8h, v3.8b, #0 -; CHECK-NEXT: sshll v5.8h, v5.8b, #0 -; CHECK-NEXT: sshll v4.8h, v4.8b, #0 -; CHECK-NEXT: sshll v21.8h, v21.8b, #0 +; CHECK-NEXT: mov v19.s[0], v24.s[0] +; CHECK-NEXT: ldr b24, [sp, #872] +; CHECK-NEXT: ld1 { v22.b }[2], [x9] +; CHECK-NEXT: add x9, sp, #944 +; CHECK-NEXT: add x11, sp, #880 +; CHECK-NEXT: add x10, sp, #768 +; CHECK-NEXT: ld1 { v18.b }[1], [x9] +; CHECK-NEXT: add x9, sp, #832 +; CHECK-NEXT: ld1 { v24.b }[1], [x11] +; CHECK-NEXT: ld1 { v23.b }[3], [x9] +; CHECK-NEXT: ld1 { v22.b }[3], [x10] +; CHECK-NEXT: add x10, sp, #952 +; CHECK-NEXT: add x12, sp, #888 +; CHECK-NEXT: add x9, sp, #592 +; CHECK-NEXT: add x11, sp, #776 +; CHECK-NEXT: ld1 { v18.b }[2], [x10] +; CHECK-NEXT: add x10, sp, #840 +; CHECK-NEXT: ld1 { v24.b }[2], [x12] +; CHECK-NEXT: ld1 { v23.b }[4], [x10] +; CHECK-NEXT: ld1 { v22.b }[4], [x11] +; CHECK-NEXT: ld1 { v20.b }[6], [x9] +; CHECK-NEXT: add x9, sp, #960 +; CHECK-NEXT: add x11, sp, #896 +; CHECK-NEXT: add x10, sp, #784 +; CHECK-NEXT: ld1 { v18.b }[3], [x9] +; CHECK-NEXT: add x9, sp, #848 +; CHECK-NEXT: ld1 { v24.b }[3], [x11] +; CHECK-NEXT: ld1 { v23.b }[5], [x9] +; CHECK-NEXT: ld1 { v22.b }[5], [x10] +; CHECK-NEXT: add x10, sp, #968 +; CHECK-NEXT: add x12, sp, #904 +; CHECK-NEXT: add x9, sp, #600 +; CHECK-NEXT: add x11, sp, #792 +; CHECK-NEXT: ld1 { v18.b }[4], [x10] +; CHECK-NEXT: add x10, sp, #856 +; CHECK-NEXT: ld1 { v24.b }[4], [x12] +; CHECK-NEXT: ld1 { v23.b }[6], [x10] +; CHECK-NEXT: ld1 { v22.b }[6], [x11] +; CHECK-NEXT: ld1 { v20.b }[7], [x9] +; CHECK-NEXT: add x9, sp, #976 +; CHECK-NEXT: add x11, sp, #912 +; CHECK-NEXT: add x10, sp, #800 +; CHECK-NEXT: ld1 { v18.b }[5], [x9] +; CHECK-NEXT: add x9, sp, #864 +; CHECK-NEXT: ld1 { v24.b }[5], [x11] +; CHECK-NEXT: ld1 { v23.b }[7], [x9] +; CHECK-NEXT: add x9, sp, #720 +; CHECK-NEXT: ld1 { v22.b }[7], [x10] +; CHECK-NEXT: add x10, sp, #984 +; CHECK-NEXT: ld1 { v17.b }[6], [x9] +; CHECK-NEXT: add x9, sp, #920 +; CHECK-NEXT: ld1 { v18.b }[6], [x10] +; CHECK-NEXT: ld1 { v24.b }[6], [x9] +; CHECK-NEXT: add x10, sp, #728 +; CHECK-NEXT: add x8, sp, #664 +; CHECK-NEXT: sshll v20.8h, v20.8b, #0 ; CHECK-NEXT: sshll v22.8h, v22.8b, #0 ; CHECK-NEXT: sshll v23.8h, v23.8b, #0 -; CHECK-NEXT: add x8, sp, #600 -; CHECK-NEXT: sshll v24.8h, v24.8b, #0 -; CHECK-NEXT: add x9, sp, #864 -; CHECK-NEXT: ld1 { v2.b }[7], [x11] -; CHECK-NEXT: ld1 { v7.b }[7], [x8] -; CHECK-NEXT: ld1 { v25.b }[7], [x9] -; CHECK-NEXT: smull v16.4s, v3.4h, v5.4h -; CHECK-NEXT: smull2 v3.4s, v3.8h, v5.8h -; CHECK-NEXT: smull v5.4s, v21.4h, v23.4h -; CHECK-NEXT: smull2 v21.4s, v21.8h, v23.8h -; CHECK-NEXT: smull2 v23.4s, v20.8h, v22.8h -; CHECK-NEXT: smlal v19.4s, v4.4h, v24.4h -; CHECK-NEXT: sshll v2.8h, v2.8b, #0 -; CHECK-NEXT: sshll v17.8h, v17.8b, #0 +; CHECK-NEXT: add x9, sp, #992 +; CHECK-NEXT: ld1 { v17.b }[7], [x10] +; CHECK-NEXT: add x10, sp, #928 +; CHECK-NEXT: ld1 { v18.b }[7], [x9] +; CHECK-NEXT: ld1 { v4.b }[7], [x8] +; CHECK-NEXT: ld1 { v24.b }[7], [x10] +; CHECK-NEXT: smlal v19.4s, v21.4h, v22.4h +; CHECK-NEXT: smull2 v21.4s, v21.8h, v22.8h +; CHECK-NEXT: smull v22.4s, v20.4h, v23.4h +; CHECK-NEXT: smull2 v20.4s, v20.8h, v23.8h ; CHECK-NEXT: sshll v0.8h, v0.8b, #0 ; CHECK-NEXT: sshll v1.8h, v1.8b, #0 -; CHECK-NEXT: sshll v7.8h, v7.8b, #0 -; CHECK-NEXT: sshll v25.8h, v25.8b, #0 -; CHECK-NEXT: smlal2 v3.4s, v2.8h, v17.8h -; CHECK-NEXT: smlal v16.4s, v2.4h, v17.4h -; CHECK-NEXT: smlal2 v23.4s, v4.8h, v24.8h -; CHECK-NEXT: smlal2 v18.4s, v0.8h, v1.8h -; CHECK-NEXT: smlal v6.4s, v0.4h, v1.4h -; CHECK-NEXT: smlal v19.4s, v20.4h, v22.4h -; CHECK-NEXT: smlal2 v21.4s, v7.8h, v25.8h -; CHECK-NEXT: smlal v5.4s, v7.4h, v25.4h -; CHECK-NEXT: add v0.4s, v18.4s, v3.4s -; CHECK-NEXT: add v1.4s, v6.4s, v16.4s -; CHECK-NEXT: add v2.4s, v23.4s, v21.4s -; CHECK-NEXT: add v3.4s, v19.4s, v5.4s +; CHECK-NEXT: sshll v3.8h, v3.8b, #0 +; CHECK-NEXT: sshll v2.8h, v2.8b, #0 +; CHECK-NEXT: sshll v17.8h, v17.8b, #0 +; CHECK-NEXT: sshll v18.8h, v18.8b, #0 +; CHECK-NEXT: sshll v4.8h, v4.8b, #0 +; CHECK-NEXT: sshll v23.8h, v24.8b, #0 +; CHECK-NEXT: smlal2 v16.4s, v1.8h, v3.8h +; CHECK-NEXT: smlal v6.4s, v1.4h, v3.4h +; CHECK-NEXT: smlal2 v7.4s, v0.8h, v2.8h +; CHECK-NEXT: smlal v5.4s, v0.4h, v2.4h +; CHECK-NEXT: smlal2 v20.4s, v17.8h, v18.8h +; CHECK-NEXT: smlal v22.4s, v17.4h, v18.4h +; CHECK-NEXT: smlal2 v21.4s, v4.8h, v23.8h +; CHECK-NEXT: smlal v19.4s, v4.4h, v23.4h +; CHECK-NEXT: add v0.4s, v7.4s, v16.4s +; CHECK-NEXT: add v1.4s, v5.4s, v6.4s +; CHECK-NEXT: add v2.4s, v21.4s, v20.4s +; CHECK-NEXT: add v3.4s, v19.4s, v22.4s ; CHECK-NEXT: add v0.4s, v1.4s, v0.4s ; CHECK-NEXT: add v1.4s, v3.4s, v2.4s ; CHECK-NEXT: add v0.4s, v0.4s, v1.4s @@ -2050,10 +2050,10 @@ define i32 @test_sdot_v33i8_double_nomla(<33 x i8> %a, <33 x i8> %b, <33 x i8> % ; CHECK-NEXT: ld1 { v3.b }[2], [x10] ; CHECK-NEXT: ld1 { v5.b }[2], [x8] ; CHECK-NEXT: add x8, sp, #176 -; CHECK-NEXT: ldr b6, [sp, #544] +; CHECK-NEXT: ldr b6, [sp, #672] ; CHECK-NEXT: ld1 { v0.b }[4], [x12] -; CHECK-NEXT: add x14, sp, #552 -; CHECK-NEXT: ldr b7, [sp, #672] +; CHECK-NEXT: add x14, sp, #680 +; CHECK-NEXT: ldr b7, [sp, #544] ; CHECK-NEXT: ld1 { v2.b }[4], [x8] ; CHECK-NEXT: add x13, sp, #40 ; CHECK-NEXT: ld1 { v6.b }[1], [x14] @@ -2061,7 +2061,7 @@ define i32 @test_sdot_v33i8_double_nomla(<33 x i8> %a, <33 x i8> %b, <33 x i8> % ; CHECK-NEXT: add x11, sp, #128 ; CHECK-NEXT: ld1 { v3.b }[3], [x13] ; CHECK-NEXT: ld1 { v0.b }[5], [x9] -; CHECK-NEXT: add x9, sp, #680 +; CHECK-NEXT: add x9, sp, #552 ; CHECK-NEXT: add x13, sp, #184 ; CHECK-NEXT: ld1 { v7.b }[1], [x9] ; CHECK-NEXT: ld1 { v2.b }[5], [x13] @@ -2070,26 +2070,26 @@ define i32 @test_sdot_v33i8_double_nomla(<33 x i8> %a, <33 x i8> %b, <33 x i8> % ; CHECK-NEXT: ld1 { v4.b }[2], [x13] ; CHECK-NEXT: add x10, sp, #136 ; CHECK-NEXT: ld1 { v0.b }[6], [x11] -; CHECK-NEXT: add x11, sp, #560 +; CHECK-NEXT: add x11, sp, #688 ; CHECK-NEXT: ld1 { v5.b }[3], [x15] ; CHECK-NEXT: ld1 { v6.b }[2], [x11] -; CHECK-NEXT: add x11, sp, #688 +; CHECK-NEXT: add x11, sp, #560 ; CHECK-NEXT: mov v1.b[3], w3 ; CHECK-NEXT: ld1 { v7.b }[2], [x11] ; CHECK-NEXT: add x9, sp, #632 ; CHECK-NEXT: add x11, sp, #512 ; CHECK-NEXT: ld1 { v0.b }[7], [x10] ; CHECK-NEXT: ld1 { v4.b }[3], [x9] -; CHECK-NEXT: add x9, sp, #568 -; CHECK-NEXT: add x10, sp, #696 +; CHECK-NEXT: add x9, sp, #696 +; CHECK-NEXT: add x10, sp, #568 ; CHECK-NEXT: ld1 { v6.b }[3], [x9] ; CHECK-NEXT: ld1 { v5.b }[4], [x11] ; CHECK-NEXT: ld1 { v7.b }[3], [x10] ; CHECK-NEXT: add x9, sp, #640 ; CHECK-NEXT: mov v1.b[4], w4 ; CHECK-NEXT: ld1 { v4.b }[4], [x9] -; CHECK-NEXT: add x9, sp, #576 -; CHECK-NEXT: add x10, sp, #704 +; CHECK-NEXT: add x9, sp, #704 +; CHECK-NEXT: add x10, sp, #576 ; CHECK-NEXT: add x11, sp, #520 ; CHECK-NEXT: ld1 { v6.b }[4], [x9] ; CHECK-NEXT: ldr b18, [sp, #736] @@ -2101,8 +2101,8 @@ define i32 @test_sdot_v33i8_double_nomla(<33 x i8> %a, <33 x i8> %b, <33 x i8> % ; CHECK-NEXT: add x9, sp, #648 ; CHECK-NEXT: ld1 { v3.b }[4], [x8] ; CHECK-NEXT: add x10, sp, #528 -; CHECK-NEXT: add x11, sp, #584 -; CHECK-NEXT: add x12, sp, #712 +; CHECK-NEXT: add x11, sp, #712 +; CHECK-NEXT: add x12, sp, #584 ; CHECK-NEXT: sshll v18.8h, v18.8b, #0 ; CHECK-NEXT: mov v1.b[5], w5 ; CHECK-NEXT: ld1 { v6.b }[5], [x11] @@ -2114,8 +2114,8 @@ define i32 @test_sdot_v33i8_double_nomla(<33 x i8> %a, <33 x i8> %b, <33 x i8> % ; CHECK-NEXT: ld1 { v3.b }[5], [x14] ; CHECK-NEXT: add x9, sp, #656 ; CHECK-NEXT: add x10, sp, #536 -; CHECK-NEXT: add x11, sp, #592 -; CHECK-NEXT: add x12, sp, #720 +; CHECK-NEXT: add x11, sp, #720 +; CHECK-NEXT: add x12, sp, #592 ; CHECK-NEXT: sshll v18.4s, v18.4h, #0 ; CHECK-NEXT: ldr b16, [sp, #208] ; CHECK-NEXT: ld1 { v6.b }[6], [x11] @@ -2127,8 +2127,8 @@ define i32 @test_sdot_v33i8_double_nomla(<33 x i8> %a, <33 x i8> %b, <33 x i8> % ; CHECK-NEXT: sshll v16.8h, v16.8b, #0 ; CHECK-NEXT: ld1 { v3.b }[6], [x8] ; CHECK-NEXT: add x8, sp, #664 -; CHECK-NEXT: add x9, sp, #600 -; CHECK-NEXT: add x10, sp, #728 +; CHECK-NEXT: add x9, sp, #728 +; CHECK-NEXT: add x10, sp, #600 ; CHECK-NEXT: mov v17.s[0], v18.s[0] ; CHECK-NEXT: ld1 { v6.b }[7], [x9] ; CHECK-NEXT: ld1 { v7.b }[7], [x10] @@ -2151,7 +2151,7 @@ define i32 @test_sdot_v33i8_double_nomla(<33 x i8> %a, <33 x i8> %b, <33 x i8> % ; CHECK-NEXT: sshll v2.8h, v2.8b, #0 ; CHECK-NEXT: sshll v3.8h, v3.8b, #0 ; CHECK-NEXT: saddl2 v16.4s, v7.8h, v6.8h -; CHECK-NEXT: saddl2 v5.4s, v4.8h, v5.8h +; CHECK-NEXT: saddl2 v5.4s, v5.8h, v4.8h ; CHECK-NEXT: saddl v6.4s, v7.4h, v6.4h ; CHECK-NEXT: saddw v4.4s, v17.4s, v4.4h ; CHECK-NEXT: saddl2 v17.4s, v1.8h, v0.8h diff --git a/llvm/test/CodeGen/RISCV/mul.ll b/llvm/test/CodeGen/RISCV/mul.ll index 364e8c7b38da..42ea425f99c0 100644 --- a/llvm/test/CodeGen/RISCV/mul.ll +++ b/llvm/test/CodeGen/RISCV/mul.ll @@ -1843,3 +1843,152 @@ define i8 @mulsub_demand_2(i8 %x, i8 %y) nounwind { %r = or i8 %a, 240 ret i8 %r } + +define i64 @muland_demand(i64 %x) nounwind { +; RV32I-LABEL: muland_demand: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -16 +; RV32I-NEXT: sw ra, 12(sp) # 4-byte Folded Spill +; RV32I-NEXT: andi a0, a0, -8 +; RV32I-NEXT: slli a1, a1, 2 +; RV32I-NEXT: srli a1, a1, 2 +; RV32I-NEXT: li a2, 12 +; RV32I-NEXT: li a3, 0 +; RV32I-NEXT: call __muldi3 +; RV32I-NEXT: lw ra, 12(sp) # 4-byte Folded Reload +; RV32I-NEXT: addi sp, sp, 16 +; RV32I-NEXT: ret +; +; RV32IM-LABEL: muland_demand: +; RV32IM: # %bb.0: +; RV32IM-NEXT: andi a0, a0, -8 +; RV32IM-NEXT: li a2, 12 +; RV32IM-NEXT: mul a1, a1, a2 +; RV32IM-NEXT: mulhu a3, a0, a2 +; RV32IM-NEXT: add a1, a3, a1 +; RV32IM-NEXT: mul a0, a0, a2 +; RV32IM-NEXT: ret +; +; RV64I-LABEL: muland_demand: +; RV64I: # %bb.0: +; RV64I-NEXT: li a1, -29 +; RV64I-NEXT: srli a1, a1, 2 +; RV64I-NEXT: and a0, a0, a1 +; RV64I-NEXT: li a1, 12 +; RV64I-NEXT: tail __muldi3 +; +; RV64IM-LABEL: muland_demand: +; RV64IM: # %bb.0: +; RV64IM-NEXT: andi a0, a0, -8 +; RV64IM-NEXT: li a1, 12 +; RV64IM-NEXT: mul a0, a0, a1 +; RV64IM-NEXT: ret + %and = and i64 %x, 4611686018427387896 + %mul = mul i64 %and, 12 + ret i64 %mul +} + +define i64 @mulzext_demand(i32 signext %x) nounwind { +; RV32I-LABEL: mulzext_demand: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -16 +; RV32I-NEXT: sw ra, 12(sp) # 4-byte Folded Spill +; RV32I-NEXT: li a3, 3 +; RV32I-NEXT: li a2, 0 +; RV32I-NEXT: call __muldi3 +; RV32I-NEXT: lw ra, 12(sp) # 4-byte Folded Reload +; RV32I-NEXT: addi sp, sp, 16 +; RV32I-NEXT: ret +; +; RV32IM-LABEL: mulzext_demand: +; RV32IM: # %bb.0: +; RV32IM-NEXT: slli a1, a0, 1 +; RV32IM-NEXT: add a1, a1, a0 +; RV32IM-NEXT: li a0, 0 +; RV32IM-NEXT: ret +; +; RV64I-LABEL: mulzext_demand: +; RV64I: # %bb.0: +; RV64I-NEXT: li a1, 3 +; RV64I-NEXT: slli a1, a1, 32 +; RV64I-NEXT: tail __muldi3 +; +; RV64IM-LABEL: mulzext_demand: +; RV64IM: # %bb.0: +; RV64IM-NEXT: li a1, 3 +; RV64IM-NEXT: slli a1, a1, 32 +; RV64IM-NEXT: mul a0, a0, a1 +; RV64IM-NEXT: ret + %ext = zext i32 %x to i64 + %mul = mul i64 %ext, 12884901888 + ret i64 %mul +} + +define i32 @mulfshl_demand(i32 signext %x) nounwind { +; RV32I-LABEL: mulfshl_demand: +; RV32I: # %bb.0: +; RV32I-NEXT: srli a0, a0, 11 +; RV32I-NEXT: lui a1, 92808 +; RV32I-NEXT: tail __mulsi3 +; +; RV32IM-LABEL: mulfshl_demand: +; RV32IM: # %bb.0: +; RV32IM-NEXT: srli a0, a0, 11 +; RV32IM-NEXT: lui a1, 92808 +; RV32IM-NEXT: mul a0, a0, a1 +; RV32IM-NEXT: ret +; +; RV64I-LABEL: mulfshl_demand: +; RV64I: # %bb.0: +; RV64I-NEXT: addi sp, sp, -16 +; RV64I-NEXT: sd ra, 8(sp) # 8-byte Folded Spill +; RV64I-NEXT: srliw a0, a0, 11 +; RV64I-NEXT: lui a1, 92808 +; RV64I-NEXT: call __muldi3 +; RV64I-NEXT: ld ra, 8(sp) # 8-byte Folded Reload +; RV64I-NEXT: addi sp, sp, 16 +; RV64I-NEXT: ret +; +; RV64IM-LABEL: mulfshl_demand: +; RV64IM: # %bb.0: +; RV64IM-NEXT: srliw a0, a0, 11 +; RV64IM-NEXT: lui a1, 92808 +; RV64IM-NEXT: mulw a0, a0, a1 +; RV64IM-NEXT: ret + %fshl = tail call i32 @llvm.fshl.i32(i32 %x, i32 %x, i32 21) + %mul = mul i32 %fshl, 380141568 + ret i32 %mul +} + +define i32 @mulor_demand(i32 signext %x, i32 signext %y) nounwind { +; RV32I-LABEL: mulor_demand: +; RV32I: # %bb.0: +; RV32I-NEXT: lui a1, 92808 +; RV32I-NEXT: tail __mulsi3 +; +; RV32IM-LABEL: mulor_demand: +; RV32IM: # %bb.0: +; RV32IM-NEXT: lui a1, 92808 +; RV32IM-NEXT: mul a0, a0, a1 +; RV32IM-NEXT: ret +; +; RV64I-LABEL: mulor_demand: +; RV64I: # %bb.0: +; RV64I-NEXT: addi sp, sp, -16 +; RV64I-NEXT: sd ra, 8(sp) # 8-byte Folded Spill +; RV64I-NEXT: lui a1, 92808 +; RV64I-NEXT: call __muldi3 +; RV64I-NEXT: ld ra, 8(sp) # 8-byte Folded Reload +; RV64I-NEXT: addi sp, sp, 16 +; RV64I-NEXT: ret +; +; RV64IM-LABEL: mulor_demand: +; RV64IM: # %bb.0: +; RV64IM-NEXT: lui a1, 92808 +; RV64IM-NEXT: mulw a0, a0, a1 +; RV64IM-NEXT: ret + %mul1 = mul i32 %y, 10485760 + %or = or disjoint i32 %mul1, %x + %mul2 = mul i32 %or, 380141568 + ret i32 %mul2 +} diff --git a/llvm/test/CodeGen/RISCV/rv64-legal-i32/rv64zba.ll b/llvm/test/CodeGen/RISCV/rv64-legal-i32/rv64zba.ll index 2db0d40b0ce5..cf7be57ccc90 100644 --- a/llvm/test/CodeGen/RISCV/rv64-legal-i32/rv64zba.ll +++ b/llvm/test/CodeGen/RISCV/rv64-legal-i32/rv64zba.ll @@ -637,8 +637,6 @@ define i64 @zext_mul288(i32 signext %a) { define i64 @zext_mul12884901888(i32 signext %a) { ; RV64I-LABEL: zext_mul12884901888: ; RV64I: # %bb.0: -; RV64I-NEXT: slli a0, a0, 32 -; RV64I-NEXT: srli a0, a0, 32 ; RV64I-NEXT: li a1, 3 ; RV64I-NEXT: slli a1, a1, 32 ; RV64I-NEXT: mul a0, a0, a1 @@ -646,8 +644,8 @@ define i64 @zext_mul12884901888(i32 signext %a) { ; ; RV64ZBA-LABEL: zext_mul12884901888: ; RV64ZBA: # %bb.0: -; RV64ZBA-NEXT: slli a0, a0, 32 ; RV64ZBA-NEXT: sh1add a0, a0, a0 +; RV64ZBA-NEXT: slli a0, a0, 32 ; RV64ZBA-NEXT: ret %b = zext i32 %a to i64 %c = mul i64 %b, 12884901888 @@ -658,8 +656,6 @@ define i64 @zext_mul12884901888(i32 signext %a) { define i64 @zext_mul21474836480(i32 signext %a) { ; RV64I-LABEL: zext_mul21474836480: ; RV64I: # %bb.0: -; RV64I-NEXT: slli a0, a0, 32 -; RV64I-NEXT: srli a0, a0, 32 ; RV64I-NEXT: li a1, 5 ; RV64I-NEXT: slli a1, a1, 32 ; RV64I-NEXT: mul a0, a0, a1 @@ -667,8 +663,8 @@ define i64 @zext_mul21474836480(i32 signext %a) { ; ; RV64ZBA-LABEL: zext_mul21474836480: ; RV64ZBA: # %bb.0: -; RV64ZBA-NEXT: slli a0, a0, 32 ; RV64ZBA-NEXT: sh2add a0, a0, a0 +; RV64ZBA-NEXT: slli a0, a0, 32 ; RV64ZBA-NEXT: ret %b = zext i32 %a to i64 %c = mul i64 %b, 21474836480 @@ -679,8 +675,6 @@ define i64 @zext_mul21474836480(i32 signext %a) { define i64 @zext_mul38654705664(i32 signext %a) { ; RV64I-LABEL: zext_mul38654705664: ; RV64I: # %bb.0: -; RV64I-NEXT: slli a0, a0, 32 -; RV64I-NEXT: srli a0, a0, 32 ; RV64I-NEXT: li a1, 9 ; RV64I-NEXT: slli a1, a1, 32 ; RV64I-NEXT: mul a0, a0, a1 @@ -688,8 +682,8 @@ define i64 @zext_mul38654705664(i32 signext %a) { ; ; RV64ZBA-LABEL: zext_mul38654705664: ; RV64ZBA: # %bb.0: -; RV64ZBA-NEXT: slli a0, a0, 32 ; RV64ZBA-NEXT: sh3add a0, a0, a0 +; RV64ZBA-NEXT: slli a0, a0, 32 ; RV64ZBA-NEXT: ret %b = zext i32 %a to i64 %c = mul i64 %b, 38654705664 diff --git a/llvm/test/CodeGen/RISCV/rv64zba.ll b/llvm/test/CodeGen/RISCV/rv64zba.ll index dc93c0215a25..4a568fb2b25c 100644 --- a/llvm/test/CodeGen/RISCV/rv64zba.ll +++ b/llvm/test/CodeGen/RISCV/rv64zba.ll @@ -856,8 +856,6 @@ define i64 @zext_mul288(i32 signext %a) { define i64 @zext_mul12884901888(i32 signext %a) { ; RV64I-LABEL: zext_mul12884901888: ; RV64I: # %bb.0: -; RV64I-NEXT: slli a0, a0, 32 -; RV64I-NEXT: srli a0, a0, 32 ; RV64I-NEXT: li a1, 3 ; RV64I-NEXT: slli a1, a1, 32 ; RV64I-NEXT: mul a0, a0, a1 @@ -865,8 +863,8 @@ define i64 @zext_mul12884901888(i32 signext %a) { ; ; RV64ZBA-LABEL: zext_mul12884901888: ; RV64ZBA: # %bb.0: -; RV64ZBA-NEXT: slli a0, a0, 32 ; RV64ZBA-NEXT: sh1add a0, a0, a0 +; RV64ZBA-NEXT: slli a0, a0, 32 ; RV64ZBA-NEXT: ret %b = zext i32 %a to i64 %c = mul i64 %b, 12884901888 @@ -877,8 +875,6 @@ define i64 @zext_mul12884901888(i32 signext %a) { define i64 @zext_mul21474836480(i32 signext %a) { ; RV64I-LABEL: zext_mul21474836480: ; RV64I: # %bb.0: -; RV64I-NEXT: slli a0, a0, 32 -; RV64I-NEXT: srli a0, a0, 32 ; RV64I-NEXT: li a1, 5 ; RV64I-NEXT: slli a1, a1, 32 ; RV64I-NEXT: mul a0, a0, a1 @@ -886,8 +882,8 @@ define i64 @zext_mul21474836480(i32 signext %a) { ; ; RV64ZBA-LABEL: zext_mul21474836480: ; RV64ZBA: # %bb.0: -; RV64ZBA-NEXT: slli a0, a0, 32 ; RV64ZBA-NEXT: sh2add a0, a0, a0 +; RV64ZBA-NEXT: slli a0, a0, 32 ; RV64ZBA-NEXT: ret %b = zext i32 %a to i64 %c = mul i64 %b, 21474836480 @@ -898,8 +894,6 @@ define i64 @zext_mul21474836480(i32 signext %a) { define i64 @zext_mul38654705664(i32 signext %a) { ; RV64I-LABEL: zext_mul38654705664: ; RV64I: # %bb.0: -; RV64I-NEXT: slli a0, a0, 32 -; RV64I-NEXT: srli a0, a0, 32 ; RV64I-NEXT: li a1, 9 ; RV64I-NEXT: slli a1, a1, 32 ; RV64I-NEXT: mul a0, a0, a1 @@ -907,8 +901,8 @@ define i64 @zext_mul38654705664(i32 signext %a) { ; ; RV64ZBA-LABEL: zext_mul38654705664: ; RV64ZBA: # %bb.0: -; RV64ZBA-NEXT: slli a0, a0, 32 ; RV64ZBA-NEXT: sh3add a0, a0, a0 +; RV64ZBA-NEXT: slli a0, a0, 32 ; RV64ZBA-NEXT: ret %b = zext i32 %a to i64 %c = mul i64 %b, 38654705664 diff --git a/llvm/test/CodeGen/RISCV/sextw-removal.ll b/llvm/test/CodeGen/RISCV/sextw-removal.ll index f707cb31e3ec..8cf78551d28f 100644 --- a/llvm/test/CodeGen/RISCV/sextw-removal.ll +++ b/llvm/test/CodeGen/RISCV/sextw-removal.ll @@ -1047,25 +1047,25 @@ define signext i32 @bug(i32 signext %x) { ; CHECK-NEXT: seqz a2, a2 ; CHECK-NEXT: slli a3, a2, 3 ; CHECK-NEXT: sllw a1, a1, a3 -; CHECK-NEXT: neg a2, a2 +; CHECK-NEXT: negw a2, a2 ; CHECK-NEXT: andi a2, a2, -8 ; CHECK-NEXT: add a0, a0, a2 ; CHECK-NEXT: srliw a2, a1, 28 ; CHECK-NEXT: seqz a2, a2 ; CHECK-NEXT: slli a3, a2, 2 ; CHECK-NEXT: sllw a1, a1, a3 -; CHECK-NEXT: neg a2, a2 +; CHECK-NEXT: negw a2, a2 ; CHECK-NEXT: andi a2, a2, -4 ; CHECK-NEXT: add a0, a0, a2 ; CHECK-NEXT: srliw a2, a1, 30 ; CHECK-NEXT: seqz a2, a2 ; CHECK-NEXT: slli a3, a2, 1 ; CHECK-NEXT: sllw a1, a1, a3 -; CHECK-NEXT: neg a2, a2 +; CHECK-NEXT: negw a2, a2 ; CHECK-NEXT: andi a2, a2, -2 ; CHECK-NEXT: add a0, a0, a2 -; CHECK-NEXT: srai a1, a1, 31 ; CHECK-NEXT: not a1, a1 +; CHECK-NEXT: srli a1, a1, 31 ; CHECK-NEXT: addw a0, a0, a1 ; CHECK-NEXT: .LBB18_4: # %cleanup ; CHECK-NEXT: ret @@ -1087,28 +1087,27 @@ define signext i32 @bug(i32 signext %x) { ; NOREMOVAL-NEXT: seqz a2, a2 ; NOREMOVAL-NEXT: slli a3, a2, 3 ; NOREMOVAL-NEXT: sllw a1, a1, a3 -; NOREMOVAL-NEXT: neg a2, a2 +; NOREMOVAL-NEXT: negw a2, a2 ; NOREMOVAL-NEXT: andi a2, a2, -8 ; NOREMOVAL-NEXT: add a0, a0, a2 ; NOREMOVAL-NEXT: srliw a2, a1, 28 ; NOREMOVAL-NEXT: seqz a2, a2 ; NOREMOVAL-NEXT: slli a3, a2, 2 ; NOREMOVAL-NEXT: sllw a1, a1, a3 -; NOREMOVAL-NEXT: neg a2, a2 +; NOREMOVAL-NEXT: negw a2, a2 ; NOREMOVAL-NEXT: andi a2, a2, -4 ; NOREMOVAL-NEXT: add a0, a0, a2 ; NOREMOVAL-NEXT: srliw a2, a1, 30 ; NOREMOVAL-NEXT: seqz a2, a2 ; NOREMOVAL-NEXT: slli a3, a2, 1 ; NOREMOVAL-NEXT: sllw a1, a1, a3 -; NOREMOVAL-NEXT: neg a2, a2 +; NOREMOVAL-NEXT: negw a2, a2 ; NOREMOVAL-NEXT: andi a2, a2, -2 ; NOREMOVAL-NEXT: add a0, a0, a2 -; NOREMOVAL-NEXT: srai a1, a1, 31 ; NOREMOVAL-NEXT: not a1, a1 -; NOREMOVAL-NEXT: add a0, a0, a1 +; NOREMOVAL-NEXT: srli a1, a1, 31 +; NOREMOVAL-NEXT: addw a0, a0, a1 ; NOREMOVAL-NEXT: .LBB18_4: # %cleanup -; NOREMOVAL-NEXT: sext.w a0, a0 ; NOREMOVAL-NEXT: ret entry: %tobool.not = icmp eq i32 %x, 0 diff --git a/llvm/test/CodeGen/Thumb2/mve-vecreduce-add.ll b/llvm/test/CodeGen/Thumb2/mve-vecreduce-add.ll index 83d7275358ce..3300d46bf856 100644 --- a/llvm/test/CodeGen/Thumb2/mve-vecreduce-add.ll +++ b/llvm/test/CodeGen/Thumb2/mve-vecreduce-add.ll @@ -130,26 +130,26 @@ define arm_aapcs_vfpcc i64 @add_v8i16_v8i64_zext(<8 x i16> %x) { ; CHECK-NEXT: vmov.i64 q1, #0xffff ; CHECK-NEXT: vand q2, q2, q1 ; CHECK-NEXT: vmov.u16 r3, q0[2] -; CHECK-NEXT: vmov r0, r1, d5 -; CHECK-NEXT: vmov r2, s8 -; CHECK-NEXT: add r0, r2 -; CHECK-NEXT: vmov.u16 r2, q0[3] -; CHECK-NEXT: vmov q2[2], q2[0], r3, r2 +; CHECK-NEXT: vmov r0, s10 +; CHECK-NEXT: vmov r1, r2, d4 +; CHECK-NEXT: add r0, r1 +; CHECK-NEXT: vmov.u16 r1, q0[3] +; CHECK-NEXT: vmov q2[2], q2[0], r3, r1 ; CHECK-NEXT: vmov.u16 r3, q0[4] ; CHECK-NEXT: vand q2, q2, q1 -; CHECK-NEXT: vmov r2, s8 -; CHECK-NEXT: add r0, r2 -; CHECK-NEXT: vmov r2, s10 -; CHECK-NEXT: add r0, r2 -; CHECK-NEXT: vmov.u16 r2, q0[5] -; CHECK-NEXT: vmov q2[2], q2[0], r3, r2 +; CHECK-NEXT: vmov r1, s8 +; CHECK-NEXT: add r0, r1 +; CHECK-NEXT: vmov r1, s10 +; CHECK-NEXT: add r0, r1 +; CHECK-NEXT: vmov.u16 r1, q0[5] +; CHECK-NEXT: vmov q2[2], q2[0], r3, r1 ; CHECK-NEXT: vand q2, q2, q1 -; CHECK-NEXT: vmov r2, s8 -; CHECK-NEXT: add r0, r2 -; CHECK-NEXT: vmov r2, r3, d5 -; CHECK-NEXT: adds r0, r0, r2 +; CHECK-NEXT: vmov r1, s8 +; CHECK-NEXT: add r0, r1 +; CHECK-NEXT: vmov r1, r3, d5 +; CHECK-NEXT: adds r0, r0, r1 +; CHECK-NEXT: adc.w r1, r2, r3 ; CHECK-NEXT: vmov.u16 r2, q0[7] -; CHECK-NEXT: adcs r1, r3 ; CHECK-NEXT: vmov.u16 r3, q0[6] ; CHECK-NEXT: vmov q0[2], q0[0], r3, r2 ; CHECK-NEXT: vand q0, q0, q1 @@ -228,8 +228,8 @@ define arm_aapcs_vfpcc i64 @add_v2i16_v2i64_zext(<2 x i16> %x) { ; CHECK: @ %bb.0: @ %entry ; CHECK-NEXT: vmov.i64 q1, #0xffff ; CHECK-NEXT: vand q0, q0, q1 -; CHECK-NEXT: vmov r0, r1, d1 -; CHECK-NEXT: vmov r2, s0 +; CHECK-NEXT: vmov r0, s2 +; CHECK-NEXT: vmov r2, r1, d0 ; CHECK-NEXT: add r0, r2 ; CHECK-NEXT: bx lr entry: @@ -397,26 +397,26 @@ define arm_aapcs_vfpcc i64 @add_v16i8_v16i64_zext(<16 x i8> %x) { ; CHECK-NEXT: vmov.i64 q1, #0xff ; CHECK-NEXT: vand q2, q2, q1 ; CHECK-NEXT: vmov.u8 r3, q0[2] -; CHECK-NEXT: vmov r0, r1, d5 -; CHECK-NEXT: vmov r2, s8 -; CHECK-NEXT: add r0, r2 -; CHECK-NEXT: vmov.u8 r2, q0[3] -; CHECK-NEXT: vmov q2[2], q2[0], r3, r2 +; CHECK-NEXT: vmov r0, s10 +; CHECK-NEXT: vmov r1, r2, d4 +; CHECK-NEXT: add r0, r1 +; CHECK-NEXT: vmov.u8 r1, q0[3] +; CHECK-NEXT: vmov q2[2], q2[0], r3, r1 ; CHECK-NEXT: vmov.u8 r3, q0[4] ; CHECK-NEXT: vand q2, q2, q1 -; CHECK-NEXT: vmov r2, s8 -; CHECK-NEXT: add r0, r2 -; CHECK-NEXT: vmov r2, s10 -; CHECK-NEXT: add r0, r2 -; CHECK-NEXT: vmov.u8 r2, q0[5] -; CHECK-NEXT: vmov q2[2], q2[0], r3, r2 +; CHECK-NEXT: vmov r1, s8 +; CHECK-NEXT: add r0, r1 +; CHECK-NEXT: vmov r1, s10 +; CHECK-NEXT: add r0, r1 +; CHECK-NEXT: vmov.u8 r1, q0[5] +; CHECK-NEXT: vmov q2[2], q2[0], r3, r1 ; CHECK-NEXT: vand q2, q2, q1 -; CHECK-NEXT: vmov r2, s8 -; CHECK-NEXT: add r0, r2 -; CHECK-NEXT: vmov r2, r3, d5 -; CHECK-NEXT: adds r0, r0, r2 +; CHECK-NEXT: vmov r1, s8 +; CHECK-NEXT: add r0, r1 +; CHECK-NEXT: vmov r1, r3, d5 +; CHECK-NEXT: adds r0, r0, r1 +; CHECK-NEXT: adc.w r1, r2, r3 ; CHECK-NEXT: vmov.u8 r2, q0[7] -; CHECK-NEXT: adcs r1, r3 ; CHECK-NEXT: vmov.u8 r3, q0[6] ; CHECK-NEXT: vmov q2[2], q2[0], r3, r2 ; CHECK-NEXT: vand q2, q2, q1 @@ -540,26 +540,26 @@ define arm_aapcs_vfpcc i64 @add_v8i8_v8i64_zext(<8 x i8> %x) { ; CHECK-NEXT: vmov q2[2], q2[0], r1, r0 ; CHECK-NEXT: vmov.u16 r3, q0[2] ; CHECK-NEXT: vand q2, q2, q1 -; CHECK-NEXT: vmov r0, r1, d5 -; CHECK-NEXT: vmov r2, s8 -; CHECK-NEXT: add r0, r2 -; CHECK-NEXT: vmov.u16 r2, q0[3] -; CHECK-NEXT: vmov q2[2], q2[0], r3, r2 +; CHECK-NEXT: vmov r0, s10 +; CHECK-NEXT: vmov r1, r2, d4 +; CHECK-NEXT: add r0, r1 +; CHECK-NEXT: vmov.u16 r1, q0[3] +; CHECK-NEXT: vmov q2[2], q2[0], r3, r1 ; CHECK-NEXT: vmov.u16 r3, q0[4] ; CHECK-NEXT: vand q2, q2, q1 -; CHECK-NEXT: vmov r2, s8 -; CHECK-NEXT: add r0, r2 -; CHECK-NEXT: vmov r2, s10 -; CHECK-NEXT: add r0, r2 -; CHECK-NEXT: vmov.u16 r2, q0[5] -; CHECK-NEXT: vmov q2[2], q2[0], r3, r2 +; CHECK-NEXT: vmov r1, s8 +; CHECK-NEXT: add r0, r1 +; CHECK-NEXT: vmov r1, s10 +; CHECK-NEXT: add r0, r1 +; CHECK-NEXT: vmov.u16 r1, q0[5] +; CHECK-NEXT: vmov q2[2], q2[0], r3, r1 ; CHECK-NEXT: vand q2, q2, q1 -; CHECK-NEXT: vmov r2, s8 -; CHECK-NEXT: add r0, r2 -; CHECK-NEXT: vmov r2, r3, d5 -; CHECK-NEXT: adds r0, r0, r2 +; CHECK-NEXT: vmov r1, s8 +; CHECK-NEXT: add r0, r1 +; CHECK-NEXT: vmov r1, r3, d5 +; CHECK-NEXT: adds r0, r0, r1 +; CHECK-NEXT: adc.w r1, r2, r3 ; CHECK-NEXT: vmov.u16 r2, q0[7] -; CHECK-NEXT: adcs r1, r3 ; CHECK-NEXT: vmov.u16 r3, q0[6] ; CHECK-NEXT: vmov q0[2], q0[0], r3, r2 ; CHECK-NEXT: vand q0, q0, q1 @@ -648,8 +648,8 @@ define arm_aapcs_vfpcc i64 @add_v2i8_v2i64_zext(<2 x i8> %x) { ; CHECK: @ %bb.0: @ %entry ; CHECK-NEXT: vmov.i64 q1, #0xff ; CHECK-NEXT: vand q0, q0, q1 -; CHECK-NEXT: vmov r0, r1, d1 -; CHECK-NEXT: vmov r2, s0 +; CHECK-NEXT: vmov r0, s2 +; CHECK-NEXT: vmov r2, r1, d0 ; CHECK-NEXT: add r0, r2 ; CHECK-NEXT: bx lr entry: @@ -834,8 +834,8 @@ define arm_aapcs_vfpcc i64 @add_v8i16_v8i64_acc_zext(<8 x i16> %x, i64 %a) { ; CHECK-NEXT: vmov q2[2], q2[0], r3, r2 ; CHECK-NEXT: vmov.i64 q1, #0xffff ; CHECK-NEXT: vand q2, q2, q1 -; CHECK-NEXT: vmov r2, r12, d5 -; CHECK-NEXT: vmov r3, s8 +; CHECK-NEXT: vmov r2, s10 +; CHECK-NEXT: vmov r3, r12, d4 ; CHECK-NEXT: add.w lr, r3, r2 ; CHECK-NEXT: vmov.u16 r3, q0[3] ; CHECK-NEXT: vmov.u16 r2, q0[2] @@ -943,8 +943,8 @@ define arm_aapcs_vfpcc i64 @add_v2i16_v2i64_acc_zext(<2 x i16> %x, i64 %a) { ; CHECK: @ %bb.0: @ %entry ; CHECK-NEXT: vmov.i64 q1, #0xffff ; CHECK-NEXT: vand q0, q0, q1 -; CHECK-NEXT: vmov r2, r12, d1 -; CHECK-NEXT: vmov r3, s0 +; CHECK-NEXT: vmov r2, s2 +; CHECK-NEXT: vmov r3, r12, d0 ; CHECK-NEXT: add r2, r3 ; CHECK-NEXT: adds r0, r0, r2 ; CHECK-NEXT: adc.w r1, r1, r12 @@ -1130,8 +1130,8 @@ define arm_aapcs_vfpcc i64 @add_v16i8_v16i64_acc_zext(<16 x i8> %x, i64 %a) { ; CHECK-NEXT: vmov q2[2], q2[0], r3, r2 ; CHECK-NEXT: vmov.i64 q1, #0xff ; CHECK-NEXT: vand q2, q2, q1 -; CHECK-NEXT: vmov r2, r12, d5 -; CHECK-NEXT: vmov r3, s8 +; CHECK-NEXT: vmov r2, s10 +; CHECK-NEXT: vmov r3, r12, d4 ; CHECK-NEXT: add.w lr, r3, r2 ; CHECK-NEXT: vmov.u8 r3, q0[3] ; CHECK-NEXT: vmov.u8 r2, q0[2] @@ -1283,8 +1283,8 @@ define arm_aapcs_vfpcc i64 @add_v8i8_v8i64_acc_zext(<8 x i8> %x, i64 %a) { ; CHECK-NEXT: vmov.u16 r3, q0[0] ; CHECK-NEXT: vmov q2[2], q2[0], r3, r2 ; CHECK-NEXT: vand q2, q2, q1 -; CHECK-NEXT: vmov r2, r12, d5 -; CHECK-NEXT: vmov r3, s8 +; CHECK-NEXT: vmov r2, s10 +; CHECK-NEXT: vmov r3, r12, d4 ; CHECK-NEXT: add.w lr, r3, r2 ; CHECK-NEXT: vmov.u16 r3, q0[3] ; CHECK-NEXT: vmov.u16 r2, q0[2] @@ -1402,8 +1402,8 @@ define arm_aapcs_vfpcc i64 @add_v2i8_v2i64_acc_zext(<2 x i8> %x, i64 %a) { ; CHECK: @ %bb.0: @ %entry ; CHECK-NEXT: vmov.i64 q1, #0xff ; CHECK-NEXT: vand q0, q0, q1 -; CHECK-NEXT: vmov r2, r12, d1 -; CHECK-NEXT: vmov r3, s0 +; CHECK-NEXT: vmov r2, s2 +; CHECK-NEXT: vmov r3, r12, d0 ; CHECK-NEXT: add r2, r3 ; CHECK-NEXT: adds r0, r0, r2 ; CHECK-NEXT: adc.w r1, r1, r12 diff --git a/llvm/test/CodeGen/X86/combine-srem.ll b/llvm/test/CodeGen/X86/combine-srem.ll index 49ce2455ae8c..4ed00a9d66bd 100644 --- a/llvm/test/CodeGen/X86/combine-srem.ll +++ b/llvm/test/CodeGen/X86/combine-srem.ll @@ -329,7 +329,7 @@ define <4 x i32> @combine_vec_srem_by_pow2b_neg(<4 x i32> %x) { ; SSE-NEXT: pblendw {{.*#+}} xmm3 = xmm3[0,1,2,3],xmm2[4,5,6,7] ; SSE-NEXT: movdqa %xmm1, %xmm2 ; SSE-NEXT: psrad $3, %xmm2 -; SSE-NEXT: psrad $1, %xmm1 +; SSE-NEXT: psrld $1, %xmm1 ; SSE-NEXT: pblendw {{.*#+}} xmm1 = xmm1[0,1,2,3],xmm2[4,5,6,7] ; SSE-NEXT: pblendw {{.*#+}} xmm1 = xmm1[0,1],xmm3[2,3],xmm1[4,5],xmm3[6,7] ; SSE-NEXT: pmulld {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm1 @@ -351,7 +351,7 @@ define <4 x i32> @combine_vec_srem_by_pow2b_neg(<4 x i32> %x) { ; AVX1-NEXT: vpsrad $2, %xmm1, %xmm3 ; AVX1-NEXT: vpblendw {{.*#+}} xmm2 = xmm3[0,1,2,3],xmm2[4,5,6,7] ; AVX1-NEXT: vpsrad $3, %xmm1, %xmm3 -; AVX1-NEXT: vpsrad $1, %xmm1, %xmm1 +; AVX1-NEXT: vpsrld $1, %xmm1, %xmm1 ; AVX1-NEXT: vpblendw {{.*#+}} xmm1 = xmm1[0,1,2,3],xmm3[4,5,6,7] ; AVX1-NEXT: vpblendw {{.*#+}} xmm1 = xmm1[0,1],xmm2[2,3],xmm1[4,5],xmm2[6,7] ; AVX1-NEXT: vpmulld {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm1, %xmm1 diff --git a/llvm/test/CodeGen/X86/pmul.ll b/llvm/test/CodeGen/X86/pmul.ll index dcded7a877ab..1f82c4a5a2d9 100644 --- a/llvm/test/CodeGen/X86/pmul.ll +++ b/llvm/test/CodeGen/X86/pmul.ll @@ -1173,13 +1173,14 @@ define <4 x i32> @mul_v4i64_zero_lower(<4 x i32> %val1, <4 x i64> %val2) { ; ; SSE41-LABEL: mul_v4i64_zero_lower: ; SSE41: # %bb.0: # %entry -; SSE41-NEXT: pshufd {{.*#+}} xmm3 = xmm0[2,1,3,3] +; SSE41-NEXT: pmovzxdq {{.*#+}} xmm3 = xmm0[0],zero,xmm0[1],zero +; SSE41-NEXT: pshufd {{.*#+}} xmm0 = xmm0[2,1,3,3] ; SSE41-NEXT: psrlq $32, %xmm2 -; SSE41-NEXT: pmuludq %xmm3, %xmm2 +; SSE41-NEXT: pmuludq %xmm0, %xmm2 ; SSE41-NEXT: psrlq $32, %xmm1 -; SSE41-NEXT: pmovzxdq {{.*#+}} xmm0 = xmm0[0],zero,xmm0[1],zero -; SSE41-NEXT: pmuludq %xmm1, %xmm0 -; SSE41-NEXT: shufps {{.*#+}} xmm0 = xmm0[0,2],xmm2[0,2] +; SSE41-NEXT: pmuludq %xmm1, %xmm3 +; SSE41-NEXT: shufps {{.*#+}} xmm3 = xmm3[0,2],xmm2[0,2] +; SSE41-NEXT: movaps %xmm3, %xmm0 ; SSE41-NEXT: retq ; ; AVX-LABEL: mul_v4i64_zero_lower: diff --git a/llvm/test/CodeGen/X86/shrink_vmul.ll b/llvm/test/CodeGen/X86/shrink_vmul.ll index 62051d170994..f3f7f0515e30 100644 --- a/llvm/test/CodeGen/X86/shrink_vmul.ll +++ b/llvm/test/CodeGen/X86/shrink_vmul.ll @@ -1863,7 +1863,7 @@ define void @mul_2xi16_varconst3(ptr nocapture readonly %a, i64 %index) { ; X86-SSE-NEXT: movl {{[0-9]+}}(%esp), %ecx ; X86-SSE-NEXT: movl c, %edx ; X86-SSE-NEXT: movd {{.*#+}} xmm0 = mem[0],zero,zero,zero -; X86-SSE-NEXT: psrld $16, %xmm0 +; X86-SSE-NEXT: pshuflw {{.*#+}} xmm0 = xmm0[1,1,1,1,4,5,6,7] ; X86-SSE-NEXT: pmuludq {{\.?LCPI[0-9]+_[0-9]+}}, %xmm0 ; X86-SSE-NEXT: psllq $32, %xmm0 ; X86-SSE-NEXT: movq %xmm0, (%edx,%eax,4) @@ -1884,7 +1884,7 @@ define void @mul_2xi16_varconst3(ptr nocapture readonly %a, i64 %index) { ; X64-SSE: # %bb.0: # %entry ; X64-SSE-NEXT: movq c(%rip), %rax ; X64-SSE-NEXT: movd {{.*#+}} xmm0 = mem[0],zero,zero,zero -; X64-SSE-NEXT: psrld $16, %xmm0 +; X64-SSE-NEXT: pshuflw {{.*#+}} xmm0 = xmm0[1,1,1,1,4,5,6,7] ; X64-SSE-NEXT: pmuludq {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0 ; X64-SSE-NEXT: psllq $32, %xmm0 ; X64-SSE-NEXT: movq %xmm0, (%rax,%rsi,4) -- GitLab From 1d4772f24d19b36ed07b2434e9e6382e18ffbe08 Mon Sep 17 00:00:00 2001 From: Mikhail Goncharov Date: Wed, 22 May 2024 16:44:35 +0200 Subject: [PATCH 129/452] [bazel] add bolt address translation header to Passes (#93014) to avoid circular dependency introduced in a9b67490b2baaa311100a64191792186ea5f2c1e --- utils/bazel/llvm-project-overlay/bolt/BUILD.bazel | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/utils/bazel/llvm-project-overlay/bolt/BUILD.bazel b/utils/bazel/llvm-project-overlay/bolt/BUILD.bazel index 1c12c8167ba4..7413b018ef32 100644 --- a/utils/bazel/llvm-project-overlay/bolt/BUILD.bazel +++ b/utils/bazel/llvm-project-overlay/bolt/BUILD.bazel @@ -167,7 +167,10 @@ cc_library( ]), hdrs = glob([ "include/bolt/Passes/*.h", - ]), + ]) + [ + # To avoid circular dependency on "Profile". + "include/bolt/Profile/BoltAddressTranslation.h", + ], includes = ["include"], deps = [ ":Core", -- GitLab From 9276a03b5492d0ac62c48c4313139dbf32d7b9e1 Mon Sep 17 00:00:00 2001 From: YunQiang Su Date: Wed, 22 May 2024 22:54:45 +0800 Subject: [PATCH 130/452] MIPS/Clang: Add more false option pairs into validateTarget (#91968) The option pairs include: -mfpxx -mips1 -msoft-float -mmsa -mmsa -mabi=32 with 32bit pre-R2 CPUs -mfpxx -mmsa -mfp32 -mmsa --- clang/lib/Basic/Targets/Mips.cpp | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/clang/lib/Basic/Targets/Mips.cpp b/clang/lib/Basic/Targets/Mips.cpp index 3a65f53c5248..174bc9d2ab99 100644 --- a/clang/lib/Basic/Targets/Mips.cpp +++ b/clang/lib/Basic/Targets/Mips.cpp @@ -273,6 +273,34 @@ bool MipsTargetInfo::validateTarget(DiagnosticsEngine &Diags) const { Diags.Report(diag::err_mips_fp64_req) << "-mfp64"; return false; } + // FPXX requires mips2+ + if (FPMode == FPXX && CPU == "mips1") { + Diags.Report(diag::err_opt_not_valid_with_opt) << "-mfpxx" << CPU; + return false; + } + // -mmsa with -msoft-float makes nonsense + if (FloatABI == SoftFloat && HasMSA) { + Diags.Report(diag::err_opt_not_valid_with_opt) << "-msoft-float" + << "-mmsa"; + return false; + } + // Option -mmsa permitted on Mips32 iff revision 2 or higher is present + if (HasMSA && (CPU == "mips1" || CPU == "mips2" || getISARev() < 2) && + ABI == "o32") { + Diags.Report(diag::err_mips_fp64_req) << "-mmsa"; + return false; + } + // MSA requires FP64 + if (FPMode == FPXX && HasMSA) { + Diags.Report(diag::err_opt_not_valid_with_opt) << "-mfpxx" + << "-mmsa"; + return false; + } + if (FPMode == FP32 && HasMSA) { + Diags.Report(diag::err_opt_not_valid_with_opt) << "-mfp32" + << "-mmsa"; + return false; + } return true; } -- GitLab From 9e0be65f24bca1bd95c25d3191c75461a080af49 Mon Sep 17 00:00:00 2001 From: Emma Pilkington Date: Wed, 22 May 2024 10:55:19 -0400 Subject: [PATCH 131/452] [AMDGPU] Fix broken MIR generated by gfx11 simulated trap lowering (#91652) This was breaking the CFG connection between uses of virtual registers after the trap and their definitions before it. Fixes SWDEV-460384. Fixes a bug in #85854. --- llvm/lib/Target/AMDGPU/SIInstrInfo.cpp | 51 +++--- .../AMDGPU/GlobalISel/legalize-trap-gfx11.mir | 89 +++++++++-- llvm/test/CodeGen/AMDGPU/trap-abis.ll | 150 ++++++++++++++++++ 3 files changed, 255 insertions(+), 35 deletions(-) diff --git a/llvm/lib/Target/AMDGPU/SIInstrInfo.cpp b/llvm/lib/Target/AMDGPU/SIInstrInfo.cpp index 08351c49b223..bb5f166e4792 100644 --- a/llvm/lib/Target/AMDGPU/SIInstrInfo.cpp +++ b/llvm/lib/Target/AMDGPU/SIInstrInfo.cpp @@ -2031,50 +2031,57 @@ MachineBasicBlock *SIInstrInfo::insertSimulatedTrap(MachineRegisterInfo &MRI, MachineInstr &MI, const DebugLoc &DL) const { MachineFunction *MF = MBB.getParent(); - MachineBasicBlock *SplitBB = MBB.splitAt(MI, /*UpdateLiveIns=*/false); - MachineBasicBlock *HaltLoop = MF->CreateMachineBasicBlock(); - MF->push_back(HaltLoop); - constexpr unsigned DoorbellIDMask = 0x3ff; constexpr unsigned ECQueueWaveAbort = 0x400; + MachineBasicBlock *TrapBB = &MBB; + MachineBasicBlock *ContBB = &MBB; + MachineBasicBlock *HaltLoopBB = MF->CreateMachineBasicBlock(); + + if (!MBB.succ_empty() || std::next(MI.getIterator()) != MBB.end()) { + ContBB = MBB.splitAt(MI, /*UpdateLiveIns=*/false); + TrapBB = MF->CreateMachineBasicBlock(); + BuildMI(MBB, MI, DL, get(AMDGPU::S_CBRANCH_EXECNZ)).addMBB(TrapBB); + MF->push_back(TrapBB); + MBB.addSuccessor(TrapBB); + } + // Start with a `s_trap 2`, if we're in PRIV=1 and we need the workaround this // will be a nop. - BuildMI(MBB, MI, DL, get(AMDGPU::S_TRAP)) + BuildMI(*TrapBB, TrapBB->end(), DL, get(AMDGPU::S_TRAP)) .addImm(static_cast(GCNSubtarget::TrapID::LLVMAMDHSATrap)); Register DoorbellReg = MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass); - BuildMI(MBB, MI, DL, get(AMDGPU::S_SENDMSG_RTN_B32), DoorbellReg) + BuildMI(*TrapBB, TrapBB->end(), DL, get(AMDGPU::S_SENDMSG_RTN_B32), + DoorbellReg) .addImm(AMDGPU::SendMsg::ID_RTN_GET_DOORBELL); - BuildMI(MBB, MI, DL, get(AMDGPU::S_MOV_B32), AMDGPU::TTMP2) + BuildMI(*TrapBB, TrapBB->end(), DL, get(AMDGPU::S_MOV_B32), AMDGPU::TTMP2) .addUse(AMDGPU::M0); Register DoorbellRegMasked = MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass); - BuildMI(MBB, MI, DL, get(AMDGPU::S_AND_B32), DoorbellRegMasked) + BuildMI(*TrapBB, TrapBB->end(), DL, get(AMDGPU::S_AND_B32), DoorbellRegMasked) .addUse(DoorbellReg) .addImm(DoorbellIDMask); Register SetWaveAbortBit = MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass); - BuildMI(MBB, MI, DL, get(AMDGPU::S_OR_B32), SetWaveAbortBit) + BuildMI(*TrapBB, TrapBB->end(), DL, get(AMDGPU::S_OR_B32), SetWaveAbortBit) .addUse(DoorbellRegMasked) .addImm(ECQueueWaveAbort); - BuildMI(MBB, MI, DL, get(AMDGPU::S_MOV_B32), AMDGPU::M0) + BuildMI(*TrapBB, TrapBB->end(), DL, get(AMDGPU::S_MOV_B32), AMDGPU::M0) .addUse(SetWaveAbortBit); - BuildMI(MBB, MI, DL, get(AMDGPU::S_SENDMSG)) + BuildMI(*TrapBB, TrapBB->end(), DL, get(AMDGPU::S_SENDMSG)) .addImm(AMDGPU::SendMsg::ID_INTERRUPT); - BuildMI(MBB, MI, DL, get(AMDGPU::S_MOV_B32), AMDGPU::M0) + BuildMI(*TrapBB, TrapBB->end(), DL, get(AMDGPU::S_MOV_B32), AMDGPU::M0) .addUse(AMDGPU::TTMP2); - BuildMI(MBB, MI, DL, get(AMDGPU::S_BRANCH)).addMBB(HaltLoop); - - BuildMI(*HaltLoop, HaltLoop->end(), DL, get(AMDGPU::S_SETHALT)).addImm(5); - BuildMI(*HaltLoop, HaltLoop->end(), DL, get(AMDGPU::S_BRANCH)) - .addMBB(HaltLoop); + BuildMI(*TrapBB, TrapBB->end(), DL, get(AMDGPU::S_BRANCH)).addMBB(HaltLoopBB); + TrapBB->addSuccessor(HaltLoopBB); - if (SplitBB != &MBB) - MBB.removeSuccessor(SplitBB); - MBB.addSuccessor(HaltLoop); - HaltLoop->addSuccessor(HaltLoop); + BuildMI(*HaltLoopBB, HaltLoopBB->end(), DL, get(AMDGPU::S_SETHALT)).addImm(5); + BuildMI(*HaltLoopBB, HaltLoopBB->end(), DL, get(AMDGPU::S_BRANCH)) + .addMBB(HaltLoopBB); + MF->push_back(HaltLoopBB); + HaltLoopBB->addSuccessor(HaltLoopBB); - return SplitBB; + return ContBB; } unsigned SIInstrInfo::getNumWaitStates(const MachineInstr &MI) { diff --git a/llvm/test/CodeGen/AMDGPU/GlobalISel/legalize-trap-gfx11.mir b/llvm/test/CodeGen/AMDGPU/GlobalISel/legalize-trap-gfx11.mir index ac98dca00be3..e3d31c702482 100644 --- a/llvm/test/CodeGen/AMDGPU/GlobalISel/legalize-trap-gfx11.mir +++ b/llvm/test/CodeGen/AMDGPU/GlobalISel/legalize-trap-gfx11.mir @@ -1,18 +1,28 @@ # NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py UTC_ARGS: --version 2 -# RUN: llc -mtriple=amdgcn--amdhsa -mcpu=gfx1100 -o - -run-pass=legalizer %s | FileCheck -check-prefix=GFX1100 %s -# RUN: llc -mtriple=amdgcn--amdhsa -mcpu=gfx11-generic --amdhsa-code-object-version=6 -o - -run-pass=legalizer %s | FileCheck -check-prefix=GFX1100 %s -# RUN: llc -mtriple=amdgcn--amdhsa -mcpu=gfx1150 -o - -run-pass=legalizer %s | FileCheck -check-prefix=GFX1150 %s +# RUN: llc -mtriple=amdgcn--amdhsa -mcpu=gfx1100 -o - -run-pass=legalizer %s -verify-machineinstrs | FileCheck -check-prefix=GFX1100 %s +# RUN: llc -mtriple=amdgcn--amdhsa -mcpu=gfx11-generic --amdhsa-code-object-version=6 -o - -run-pass=legalizer %s -verify-machineinstrs | FileCheck -check-prefix=GFX1100 %s +# RUN: llc -mtriple=amdgcn--amdhsa -mcpu=gfx1150 -o - -run-pass=legalizer %s -verify-machineinstrs | FileCheck -check-prefix=GFX1150 %s --- name: test_trap body: | bb.0: ; GFX1100-LABEL: name: test_trap - ; GFX1100: successors: %bb.2(0x80000000) + ; GFX1100: successors: %bb.1(0x40000000), %bb.2(0x40000000) ; GFX1100-NEXT: {{ $}} ; GFX1100-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 0 ; GFX1100-NEXT: [[C1:%[0-9]+]]:_(p1) = G_CONSTANT i64 0 ; GFX1100-NEXT: G_STORE [[C]](s32), [[C1]](p1) :: (store (s8), addrspace 1) + ; GFX1100-NEXT: S_CBRANCH_EXECNZ %bb.2, implicit $exec + ; GFX1100-NEXT: {{ $}} + ; GFX1100-NEXT: .1: + ; GFX1100-NEXT: successors: + ; GFX1100-NEXT: {{ $}} + ; GFX1100-NEXT: G_STORE [[C]](s32), [[C1]](p1) :: (store (s8), addrspace 1) + ; GFX1100-NEXT: {{ $}} + ; GFX1100-NEXT: .2: + ; GFX1100-NEXT: successors: %bb.3(0x80000000) + ; GFX1100-NEXT: {{ $}} ; GFX1100-NEXT: S_TRAP 2 ; GFX1100-NEXT: [[S_SENDMSG_RTN_B32_:%[0-9]+]]:sreg_32 = S_SENDMSG_RTN_B32 128 ; GFX1100-NEXT: $ttmp2 = S_MOV_B32 $m0 @@ -21,18 +31,13 @@ body: | ; GFX1100-NEXT: $m0 = S_MOV_B32 [[S_OR_B32_]] ; GFX1100-NEXT: S_SENDMSG 1, implicit $exec, implicit $m0 ; GFX1100-NEXT: $m0 = S_MOV_B32 $ttmp2 - ; GFX1100-NEXT: S_BRANCH %bb.2 - ; GFX1100-NEXT: {{ $}} - ; GFX1100-NEXT: .1: - ; GFX1100-NEXT: successors: + ; GFX1100-NEXT: S_BRANCH %bb.3 ; GFX1100-NEXT: {{ $}} - ; GFX1100-NEXT: G_STORE [[C]](s32), [[C1]](p1) :: (store (s8), addrspace 1) - ; GFX1100-NEXT: {{ $}} - ; GFX1100-NEXT: .2: - ; GFX1100-NEXT: successors: %bb.2(0x80000000) + ; GFX1100-NEXT: .3: + ; GFX1100-NEXT: successors: %bb.3(0x80000000) ; GFX1100-NEXT: {{ $}} ; GFX1100-NEXT: S_SETHALT 5 - ; GFX1100-NEXT: S_BRANCH %bb.2 + ; GFX1100-NEXT: S_BRANCH %bb.3 ; ; GFX1150-LABEL: name: test_trap ; GFX1150: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 0 @@ -45,5 +50,63 @@ body: | G_STORE %0, %1 :: (store 1, addrspace 1) G_TRAP G_STORE %0, %1 :: (store 1, addrspace 1) +... + +--- +name: test_fallthrough_trap +body: | + ; GFX1100-LABEL: name: test_fallthrough_trap + ; GFX1100: bb.0: + ; GFX1100-NEXT: successors: %bb.1(0x80000000), %bb.2(0x00000000) + ; GFX1100-NEXT: {{ $}} + ; GFX1100-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 0 + ; GFX1100-NEXT: [[C1:%[0-9]+]]:_(p1) = G_CONSTANT i64 0 + ; GFX1100-NEXT: G_STORE [[C]](s32), [[C1]](p1) :: (store (s8), addrspace 1) + ; GFX1100-NEXT: S_CBRANCH_EXECNZ %bb.2, implicit $exec + ; GFX1100-NEXT: {{ $}} + ; GFX1100-NEXT: bb.1: + ; GFX1100-NEXT: successors: + ; GFX1100-NEXT: {{ $}} + ; GFX1100-NEXT: G_STORE [[C]](s32), [[C1]](p1) :: (store (s8), addrspace 1) + ; GFX1100-NEXT: {{ $}} + ; GFX1100-NEXT: bb.2: + ; GFX1100-NEXT: successors: %bb.3(0x80000000) + ; GFX1100-NEXT: {{ $}} + ; GFX1100-NEXT: S_TRAP 2 + ; GFX1100-NEXT: [[S_SENDMSG_RTN_B32_:%[0-9]+]]:sreg_32 = S_SENDMSG_RTN_B32 128 + ; GFX1100-NEXT: $ttmp2 = S_MOV_B32 $m0 + ; GFX1100-NEXT: [[S_AND_B32_:%[0-9]+]]:sreg_32 = S_AND_B32 [[S_SENDMSG_RTN_B32_]], 1023, implicit-def $scc + ; GFX1100-NEXT: [[S_OR_B32_:%[0-9]+]]:sreg_32 = S_OR_B32 [[S_AND_B32_]], 1024, implicit-def $scc + ; GFX1100-NEXT: $m0 = S_MOV_B32 [[S_OR_B32_]] + ; GFX1100-NEXT: S_SENDMSG 1, implicit $exec, implicit $m0 + ; GFX1100-NEXT: $m0 = S_MOV_B32 $ttmp2 + ; GFX1100-NEXT: S_BRANCH %bb.3 + ; GFX1100-NEXT: {{ $}} + ; GFX1100-NEXT: bb.3: + ; GFX1100-NEXT: successors: %bb.3(0x80000000) + ; GFX1100-NEXT: {{ $}} + ; GFX1100-NEXT: S_SETHALT 5 + ; GFX1100-NEXT: S_BRANCH %bb.3 + ; + ; GFX1150-LABEL: name: test_fallthrough_trap + ; GFX1150: bb.0: + ; GFX1150-NEXT: successors: %bb.1(0x80000000) + ; GFX1150-NEXT: {{ $}} + ; GFX1150-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 0 + ; GFX1150-NEXT: [[C1:%[0-9]+]]:_(p1) = G_CONSTANT i64 0 + ; GFX1150-NEXT: G_STORE [[C]](s32), [[C1]](p1) :: (store (s8), addrspace 1) + ; GFX1150-NEXT: S_TRAP 2 + ; GFX1150-NEXT: {{ $}} + ; GFX1150-NEXT: bb.1: + ; GFX1150-NEXT: G_STORE [[C]](s32), [[C1]](p1) :: (store (s8), addrspace 1) + bb.0: + successors: %bb.1 + + %0:_(s8) = G_CONSTANT i8 0 + %1:_(p1) = G_CONSTANT i64 0 + G_STORE %0, %1 :: (store 1, addrspace 1) + G_TRAP + bb.1: + G_STORE %0, %1 :: (store 1, addrspace 1) ... diff --git a/llvm/test/CodeGen/AMDGPU/trap-abis.ll b/llvm/test/CodeGen/AMDGPU/trap-abis.ll index dcc5fbd142c4..7dce633e9186 100644 --- a/llvm/test/CodeGen/AMDGPU/trap-abis.ll +++ b/llvm/test/CodeGen/AMDGPU/trap-abis.ll @@ -264,6 +264,142 @@ ret: ret void } +define amdgpu_kernel void @trap_with_use_after(ptr addrspace(1) %arg0, ptr addrspace(1) %arg1) { +; NOHSA-TRAP-GFX900-LABEL: trap_with_use_after: +; NOHSA-TRAP-GFX900: ; %bb.0: +; NOHSA-TRAP-GFX900-NEXT: s_load_dwordx4 s[0:3], s[0:1], 0x24 +; NOHSA-TRAP-GFX900-NEXT: v_mov_b32_e32 v0, 0 +; NOHSA-TRAP-GFX900-NEXT: s_waitcnt lgkmcnt(0) +; NOHSA-TRAP-GFX900-NEXT: global_load_dword v1, v0, s[0:1] glc +; NOHSA-TRAP-GFX900-NEXT: s_waitcnt vmcnt(0) +; NOHSA-TRAP-GFX900-NEXT: s_cbranch_execnz .LBB2_2 +; NOHSA-TRAP-GFX900-NEXT: ; %bb.1: +; NOHSA-TRAP-GFX900-NEXT: global_store_dword v0, v1, s[2:3] +; NOHSA-TRAP-GFX900-NEXT: s_waitcnt vmcnt(0) +; NOHSA-TRAP-GFX900-NEXT: .LBB2_2: +; NOHSA-TRAP-GFX900-NEXT: s_endpgm +; +; HSA-TRAP-GFX803-LABEL: trap_with_use_after: +; HSA-TRAP-GFX803: ; %bb.0: +; HSA-TRAP-GFX803-NEXT: s_mov_b64 s[0:1], s[4:5] +; HSA-TRAP-GFX803-NEXT: s_load_dwordx4 s[4:7], s[6:7], 0x0 +; HSA-TRAP-GFX803-NEXT: s_waitcnt lgkmcnt(0) +; HSA-TRAP-GFX803-NEXT: v_mov_b32_e32 v0, s4 +; HSA-TRAP-GFX803-NEXT: v_mov_b32_e32 v1, s5 +; HSA-TRAP-GFX803-NEXT: flat_load_dword v2, v[0:1] glc +; HSA-TRAP-GFX803-NEXT: s_waitcnt vmcnt(0) +; HSA-TRAP-GFX803-NEXT: v_mov_b32_e32 v0, s6 +; HSA-TRAP-GFX803-NEXT: v_mov_b32_e32 v1, s7 +; HSA-TRAP-GFX803-NEXT: s_trap 2 +; HSA-TRAP-GFX803-NEXT: flat_store_dword v[0:1], v2 +; HSA-TRAP-GFX803-NEXT: s_waitcnt vmcnt(0) +; HSA-TRAP-GFX803-NEXT: s_endpgm +; +; HSA-TRAP-GFX900-LABEL: trap_with_use_after: +; HSA-TRAP-GFX900: ; %bb.0: +; HSA-TRAP-GFX900-NEXT: s_load_dwordx4 s[0:3], s[4:5], 0x0 +; HSA-TRAP-GFX900-NEXT: v_mov_b32_e32 v0, 0 +; HSA-TRAP-GFX900-NEXT: s_waitcnt lgkmcnt(0) +; HSA-TRAP-GFX900-NEXT: global_load_dword v1, v0, s[0:1] glc +; HSA-TRAP-GFX900-NEXT: s_waitcnt vmcnt(0) +; HSA-TRAP-GFX900-NEXT: s_trap 2 +; HSA-TRAP-GFX900-NEXT: global_store_dword v0, v1, s[2:3] +; HSA-TRAP-GFX900-NEXT: s_waitcnt vmcnt(0) +; HSA-TRAP-GFX900-NEXT: s_endpgm +; +; HSA-NOTRAP-GFX900-LABEL: trap_with_use_after: +; HSA-NOTRAP-GFX900: ; %bb.0: +; HSA-NOTRAP-GFX900-NEXT: s_load_dwordx4 s[0:3], s[4:5], 0x0 +; HSA-NOTRAP-GFX900-NEXT: v_mov_b32_e32 v0, 0 +; HSA-NOTRAP-GFX900-NEXT: s_waitcnt lgkmcnt(0) +; HSA-NOTRAP-GFX900-NEXT: global_load_dword v1, v0, s[0:1] glc +; HSA-NOTRAP-GFX900-NEXT: s_waitcnt vmcnt(0) +; HSA-NOTRAP-GFX900-NEXT: s_cbranch_execnz .LBB2_2 +; HSA-NOTRAP-GFX900-NEXT: ; %bb.1: +; HSA-NOTRAP-GFX900-NEXT: global_store_dword v0, v1, s[2:3] +; HSA-NOTRAP-GFX900-NEXT: s_waitcnt vmcnt(0) +; HSA-NOTRAP-GFX900-NEXT: .LBB2_2: +; HSA-NOTRAP-GFX900-NEXT: s_endpgm +; +; HSA-TRAP-GFX1100-LABEL: trap_with_use_after: +; HSA-TRAP-GFX1100: ; %bb.0: +; HSA-TRAP-GFX1100-NEXT: s_load_b128 s[0:3], s[0:1], 0x0 +; HSA-TRAP-GFX1100-NEXT: v_mov_b32_e32 v0, 0 +; HSA-TRAP-GFX1100-NEXT: s_waitcnt lgkmcnt(0) +; HSA-TRAP-GFX1100-NEXT: global_load_b32 v1, v0, s[0:1] glc dlc +; HSA-TRAP-GFX1100-NEXT: s_waitcnt vmcnt(0) +; HSA-TRAP-GFX1100-NEXT: s_cbranch_execnz .LBB2_2 +; HSA-TRAP-GFX1100-NEXT: ; %bb.1: +; HSA-TRAP-GFX1100-NEXT: global_store_b32 v0, v1, s[2:3] dlc +; HSA-TRAP-GFX1100-NEXT: s_waitcnt_vscnt null, 0x0 +; HSA-TRAP-GFX1100-NEXT: s_nop 0 +; HSA-TRAP-GFX1100-NEXT: s_sendmsg sendmsg(MSG_DEALLOC_VGPRS) +; HSA-TRAP-GFX1100-NEXT: s_endpgm +; HSA-TRAP-GFX1100-NEXT: .LBB2_2: +; HSA-TRAP-GFX1100-NEXT: s_trap 2 +; HSA-TRAP-GFX1100-NEXT: s_sendmsg_rtn_b32 s0, sendmsg(MSG_RTN_GET_DOORBELL) +; HSA-TRAP-GFX1100-NEXT: s_mov_b32 ttmp2, m0 +; HSA-TRAP-GFX1100-NEXT: s_waitcnt lgkmcnt(0) +; HSA-TRAP-GFX1100-NEXT: s_and_b32 s0, s0, 0x3ff +; HSA-TRAP-GFX1100-NEXT: s_delay_alu instid0(SALU_CYCLE_1) | instskip(NEXT) | instid1(SALU_CYCLE_1) +; HSA-TRAP-GFX1100-NEXT: s_bitset1_b32 s0, 10 +; HSA-TRAP-GFX1100-NEXT: s_mov_b32 m0, s0 +; HSA-TRAP-GFX1100-NEXT: s_sendmsg sendmsg(MSG_INTERRUPT) +; HSA-TRAP-GFX1100-NEXT: s_mov_b32 m0, ttmp2 +; HSA-TRAP-GFX1100-NEXT: .LBB2_3: ; =>This Inner Loop Header: Depth=1 +; HSA-TRAP-GFX1100-NEXT: s_sethalt 5 +; HSA-TRAP-GFX1100-NEXT: s_branch .LBB2_3 +; +; HSA-TRAP-GFX1100-O0-LABEL: trap_with_use_after: +; HSA-TRAP-GFX1100-O0: ; %bb.0: +; HSA-TRAP-GFX1100-O0-NEXT: ; implicit-def: $vgpr1 : SGPR spill to VGPR lane +; HSA-TRAP-GFX1100-O0-NEXT: v_mov_b32_e32 v0, 0 +; HSA-TRAP-GFX1100-O0-NEXT: scratch_store_b32 off, v0, off offset:8 ; 4-byte Folded Spill +; HSA-TRAP-GFX1100-O0-NEXT: s_load_b64 s[0:1], s[4:5], 0x0 +; HSA-TRAP-GFX1100-O0-NEXT: s_load_b64 s[2:3], s[4:5], 0x8 +; HSA-TRAP-GFX1100-O0-NEXT: s_waitcnt lgkmcnt(0) +; HSA-TRAP-GFX1100-O0-NEXT: v_writelane_b32 v1, s2, 0 +; HSA-TRAP-GFX1100-O0-NEXT: v_writelane_b32 v1, s3, 1 +; HSA-TRAP-GFX1100-O0-NEXT: s_or_saveexec_b32 s6, -1 +; HSA-TRAP-GFX1100-O0-NEXT: scratch_store_b32 off, v1, off offset:4 ; 4-byte Folded Spill +; HSA-TRAP-GFX1100-O0-NEXT: s_mov_b32 exec_lo, s6 +; HSA-TRAP-GFX1100-O0-NEXT: global_load_b32 v0, v0, s[0:1] glc dlc +; HSA-TRAP-GFX1100-O0-NEXT: s_waitcnt vmcnt(0) +; HSA-TRAP-GFX1100-O0-NEXT: scratch_store_b32 off, v0, off ; 4-byte Folded Spill +; HSA-TRAP-GFX1100-O0-NEXT: s_cbranch_execnz .LBB2_2 +; HSA-TRAP-GFX1100-O0-NEXT: ; %bb.1: +; HSA-TRAP-GFX1100-O0-NEXT: s_or_saveexec_b32 s6, -1 +; HSA-TRAP-GFX1100-O0-NEXT: scratch_load_b32 v0, off, off offset:4 ; 4-byte Folded Reload +; HSA-TRAP-GFX1100-O0-NEXT: s_mov_b32 exec_lo, s6 +; HSA-TRAP-GFX1100-O0-NEXT: s_waitcnt vmcnt(0) +; HSA-TRAP-GFX1100-O0-NEXT: v_readlane_b32 s0, v0, 0 +; HSA-TRAP-GFX1100-O0-NEXT: v_readlane_b32 s1, v0, 1 +; HSA-TRAP-GFX1100-O0-NEXT: scratch_load_b32 v1, off, off offset:8 ; 4-byte Folded Reload +; HSA-TRAP-GFX1100-O0-NEXT: scratch_load_b32 v2, off, off ; 4-byte Folded Reload +; HSA-TRAP-GFX1100-O0-NEXT: s_waitcnt vmcnt(0) +; HSA-TRAP-GFX1100-O0-NEXT: global_store_b32 v1, v2, s[0:1] dlc +; HSA-TRAP-GFX1100-O0-NEXT: s_waitcnt_vscnt null, 0x0 +; HSA-TRAP-GFX1100-O0-NEXT: ; kill: killed $vgpr0 +; HSA-TRAP-GFX1100-O0-NEXT: s_endpgm +; HSA-TRAP-GFX1100-O0-NEXT: .LBB2_2: +; HSA-TRAP-GFX1100-O0-NEXT: s_trap 2 +; HSA-TRAP-GFX1100-O0-NEXT: s_sendmsg_rtn_b32 s0, sendmsg(MSG_RTN_GET_DOORBELL) +; HSA-TRAP-GFX1100-O0-NEXT: s_mov_b32 ttmp2, m0 +; HSA-TRAP-GFX1100-O0-NEXT: s_waitcnt lgkmcnt(0) +; HSA-TRAP-GFX1100-O0-NEXT: s_and_b32 s0, s0, 0x3ff +; HSA-TRAP-GFX1100-O0-NEXT: s_or_b32 s0, s0, 0x400 +; HSA-TRAP-GFX1100-O0-NEXT: s_mov_b32 m0, s0 +; HSA-TRAP-GFX1100-O0-NEXT: s_sendmsg sendmsg(MSG_INTERRUPT) +; HSA-TRAP-GFX1100-O0-NEXT: s_mov_b32 m0, ttmp2 +; HSA-TRAP-GFX1100-O0-NEXT: .LBB2_3: ; =>This Inner Loop Header: Depth=1 +; HSA-TRAP-GFX1100-O0-NEXT: s_sethalt 5 +; HSA-TRAP-GFX1100-O0-NEXT: s_branch .LBB2_3 + %tmp = load volatile i32, ptr addrspace(1) %arg0 + call void @llvm.trap() + store volatile i32 %tmp, ptr addrspace(1) %arg1 + ret void +} + define amdgpu_kernel void @debugtrap(ptr addrspace(1) nocapture readonly %arg0) { ; NOHSA-TRAP-GFX900-LABEL: debugtrap: ; NOHSA-TRAP-GFX900: ; %bb.0: @@ -334,6 +470,20 @@ define amdgpu_kernel void @debugtrap(ptr addrspace(1) nocapture readonly %arg0) ; HSA-TRAP-GFX1100-NEXT: s_nop 0 ; HSA-TRAP-GFX1100-NEXT: s_sendmsg sendmsg(MSG_DEALLOC_VGPRS) ; HSA-TRAP-GFX1100-NEXT: s_endpgm +; +; HSA-TRAP-GFX1100-O0-LABEL: debugtrap: +; HSA-TRAP-GFX1100-O0: ; %bb.0: +; HSA-TRAP-GFX1100-O0-NEXT: s_load_b64 s[0:1], s[4:5], 0x0 +; HSA-TRAP-GFX1100-O0-NEXT: v_mov_b32_e32 v0, 0 +; HSA-TRAP-GFX1100-O0-NEXT: v_mov_b32_e32 v1, 1 +; HSA-TRAP-GFX1100-O0-NEXT: s_waitcnt lgkmcnt(0) +; HSA-TRAP-GFX1100-O0-NEXT: global_store_b32 v0, v1, s[0:1] dlc +; HSA-TRAP-GFX1100-O0-NEXT: s_waitcnt_vscnt null, 0x0 +; HSA-TRAP-GFX1100-O0-NEXT: s_trap 3 +; HSA-TRAP-GFX1100-O0-NEXT: v_mov_b32_e32 v1, 2 +; HSA-TRAP-GFX1100-O0-NEXT: global_store_b32 v0, v1, s[0:1] dlc +; HSA-TRAP-GFX1100-O0-NEXT: s_waitcnt_vscnt null, 0x0 +; HSA-TRAP-GFX1100-O0-NEXT: s_endpgm store volatile i32 1, ptr addrspace(1) %arg0 call void @llvm.debugtrap() store volatile i32 2, ptr addrspace(1) %arg0 -- GitLab From a70ecfb267e1fe7d72c94a3cf1675b1f8df99860 Mon Sep 17 00:00:00 2001 From: Mikhail Goncharov Date: Wed, 22 May 2024 17:01:57 +0200 Subject: [PATCH 132/452] [bazel] fix build for b00e0c167186d69e1e6bceda57c09b272bd6acfc --- utils/bazel/llvm-project-overlay/mlir/BUILD.bazel | 3 +++ 1 file changed, 3 insertions(+) diff --git a/utils/bazel/llvm-project-overlay/mlir/BUILD.bazel b/utils/bazel/llvm-project-overlay/mlir/BUILD.bazel index 971c851a5f89..765a950e839d 100644 --- a/utils/bazel/llvm-project-overlay/mlir/BUILD.bazel +++ b/utils/bazel/llvm-project-overlay/mlir/BUILD.bazel @@ -8722,6 +8722,7 @@ cc_library( ], includes = ["include"], deps = [ + ":Analysis", ":DLTIDialect", ":IR", ":LLVMConversionIncGen", @@ -8956,6 +8957,7 @@ cc_library( hdrs = glob(["include/mlir/Target/LLVMIR/Dialect/OpenACC/*.h"]), includes = ["include"], deps = [ + ":Analysis", ":IR", ":LLVMDialect", ":OpenACCDialect", @@ -8975,6 +8977,7 @@ cc_library( hdrs = glob(["include/mlir/Target/LLVMIR/Dialect/OpenMP/*.h"]), includes = ["include"], deps = [ + ":Analysis", ":IR", ":LLVMDialect", ":OpenMPCommon", -- GitLab From d41dde70c44a10f9761242df73fdd288c4660c8d Mon Sep 17 00:00:00 2001 From: Matt Arsenault Date: Wed, 22 May 2024 17:04:17 +0200 Subject: [PATCH 133/452] LiveRangeEdit: Replace setIsDead with an assert (#92964) I noticed this was possibly buggy with implicit operands with the same dest register, and should maybe be using addRegisterDead. However, this is never called in a situation where the operand wasn't already marked dead. This is eliminateDeadDef, implying the def was already known to be dead. Add an assert to detect inconsistencies in dead flags. This was apparently added in 9a16d655c71826bef98b7d6e9590e4494ac0e1a9. --- llvm/lib/CodeGen/LiveRangeEdit.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/llvm/lib/CodeGen/LiveRangeEdit.cpp b/llvm/lib/CodeGen/LiveRangeEdit.cpp index 643370f0573d..7b7b5459ad7b 100644 --- a/llvm/lib/CodeGen/LiveRangeEdit.cpp +++ b/llvm/lib/CodeGen/LiveRangeEdit.cpp @@ -414,7 +414,7 @@ void LiveRangeEdit::eliminateDeadDef(MachineInstr *MI, ToShrinkSet &ToShrink) { DeadRemats->insert(MI); const TargetRegisterInfo &TRI = *MRI.getTargetRegisterInfo(); MI->substituteRegister(Dest, NewLI.reg(), 0, TRI); - MI->getOperand(0).setIsDead(true); + assert(MI->registerDefIsDead(NewLI.reg(), &TRI)); } else { if (TheDelegate) TheDelegate->LRE_WillEraseInstruction(MI); -- GitLab From bd46067abf6a3ed712f24670cf7c4b1e574a9739 Mon Sep 17 00:00:00 2001 From: Mikhail Goncharov Date: Wed, 22 May 2024 17:05:35 +0200 Subject: [PATCH 134/452] [bazel] fix build for 7630379156ec08c9d7b1ea3c03c09e7dc89ef4ee --- utils/bazel/llvm-project-overlay/mlir/BUILD.bazel | 1 + 1 file changed, 1 insertion(+) diff --git a/utils/bazel/llvm-project-overlay/mlir/BUILD.bazel b/utils/bazel/llvm-project-overlay/mlir/BUILD.bazel index 765a950e839d..614fe511d43a 100644 --- a/utils/bazel/llvm-project-overlay/mlir/BUILD.bazel +++ b/utils/bazel/llvm-project-overlay/mlir/BUILD.bazel @@ -8366,6 +8366,7 @@ cc_library( ":ArithDialect", ":ConversionPassIncGen", ":EmitCDialect", + ":PDLLAST", ":Pass", ":TransformUtils", ], -- GitLab From 154d93b7f258cdf1157b5e5d61dd9477ffd3db53 Mon Sep 17 00:00:00 2001 From: Jay Foad Date: Wed, 22 May 2024 16:04:10 +0100 Subject: [PATCH 135/452] [AMDGPU] Add a negative test for DPP combine into v_mul_lo_u32 --- llvm/test/CodeGen/AMDGPU/dpp_combine.ll | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/llvm/test/CodeGen/AMDGPU/dpp_combine.ll b/llvm/test/CodeGen/AMDGPU/dpp_combine.ll index cfc166ec798f..5162092f78ac 100644 --- a/llvm/test/CodeGen/AMDGPU/dpp_combine.ll +++ b/llvm/test/CodeGen/AMDGPU/dpp_combine.ll @@ -47,6 +47,21 @@ define amdgpu_kernel void @dpp_fadd(ptr addrspace(1) %arg) { ret void } +; Fails to combine because v_mul_lo_u32 has no e32 or dpp form. +; GCN-LABEL: {{^}}dpp_mul: +; GCN: global_load_{{dword|b32}} [[V:v[0-9]+]], +; GCN: v_mov_b32_e32 [[V2:v[0-9]+]], [[V]] +; GCN: v_mov_b32_dpp [[V2]], [[V2]] quad_perm:[1,0,0,0] row_mask:0xf bank_mask:0xf bound_ctrl:1{{$}} +; GCN: v_mul_lo_u32 [[V]], [[V2]], [[V]]{{$}} +define amdgpu_kernel void @dpp_mul(ptr addrspace(1) %arg) { + %id = tail call i32 @llvm.amdgcn.workitem.id.x() + %gep = getelementptr inbounds i32, ptr addrspace(1) %arg, i32 %id + %load = load i32, ptr addrspace(1) %gep + %tmp0 = call i32 @llvm.amdgcn.update.dpp.i32(i32 %load, i32 %load, i32 1, i32 15, i32 15, i1 1) + %mul = mul i32 %tmp0, %load + store i32 %mul, ptr addrspace(1) %gep + ret void +} declare i32 @llvm.amdgcn.workitem.id.x() declare i32 @llvm.amdgcn.update.dpp.i32(i32, i32, i32, i32, i32, i1) #0 -- GitLab From 30d484fa994577216736e797b6c6e74483a56641 Mon Sep 17 00:00:00 2001 From: Alexey Bataev Date: Wed, 22 May 2024 07:13:38 -0700 Subject: [PATCH 136/452] [SLP]Fix a crash when trying to convert masked gather nodes to strided. Need to check if the loads node is masked gather. Only vectorized loads can be converted to strided. --- .../Transforms/Vectorize/SLPVectorizer.cpp | 4 +++ .../RISCV/scatter-vectorize-reversed.ll | 30 +++++++++++++++++++ 2 files changed, 34 insertions(+) create mode 100644 llvm/test/Transforms/SLPVectorizer/RISCV/scatter-vectorize-reversed.ll diff --git a/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp b/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp index 140a1b1ffbaf..77bb6e9a6a9b 100644 --- a/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp +++ b/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp @@ -7966,6 +7966,10 @@ void BoUpSLP::transformNodes() { TreeEntry &E = *TE.get(); switch (E.getOpcode()) { case Instruction::Load: { + // No need to reorder masked gather loads, just reorder the scalar + // operands. + if (E.State != TreeEntry::Vectorize) + break; Type *ScalarTy = E.getMainOp()->getType(); auto *VecTy = FixedVectorType::get(ScalarTy, E.Scalars.size()); Align CommonAlignment = computeCommonAlignment(E.Scalars); diff --git a/llvm/test/Transforms/SLPVectorizer/RISCV/scatter-vectorize-reversed.ll b/llvm/test/Transforms/SLPVectorizer/RISCV/scatter-vectorize-reversed.ll new file mode 100644 index 000000000000..2daa3b58e5c3 --- /dev/null +++ b/llvm/test/Transforms/SLPVectorizer/RISCV/scatter-vectorize-reversed.ll @@ -0,0 +1,30 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 4 +; RUN: opt -S --passes=slp-vectorizer -mtriple=riscv64-unknown-linux-gnu -mattr=+v -slp-threshold=-11 < %s | FileCheck %s + +define <4 x i32> @test(<2 x i64> %v, ptr %p) { +; CHECK-LABEL: define <4 x i32> @test( +; CHECK-SAME: <2 x i64> [[V:%.*]], ptr [[P:%.*]]) #[[ATTR0:[0-9]+]] { +; CHECK-NEXT: entry: +; CHECK-NEXT: [[TMP0:%.*]] = insertelement <2 x ptr> poison, ptr [[P]], i32 0 +; CHECK-NEXT: [[TMP1:%.*]] = shufflevector <2 x ptr> [[TMP0]], <2 x ptr> poison, <2 x i32> zeroinitializer +; CHECK-NEXT: [[TMP2:%.*]] = getelementptr i16, <2 x ptr> [[TMP1]], <2 x i64> [[V]] +; CHECK-NEXT: [[TMP3:%.*]] = call <2 x i16> @llvm.masked.gather.v2i16.v2p0(<2 x ptr> [[TMP2]], i32 2, <2 x i1> , <2 x i16> poison) +; CHECK-NEXT: [[TMP4:%.*]] = shufflevector <2 x i16> [[TMP3]], <2 x i16> poison, <2 x i32> +; CHECK-NEXT: [[TMP7:%.*]] = zext <2 x i16> [[TMP4]] to <2 x i32> +; CHECK-NEXT: [[TMP6:%.*]] = shufflevector <2 x i32> [[TMP7]], <2 x i32> poison, <4 x i32> +; CHECK-NEXT: [[TMP5:%.*]] = shufflevector <4 x i32> zeroinitializer, <4 x i32> [[TMP6]], <4 x i32> +; CHECK-NEXT: ret <4 x i32> [[TMP5]] +; +entry: + %0 = extractelement <2 x i64> %v, i32 1 + %arrayidx127.2 = getelementptr i16, ptr %p, i64 %0 + %1 = load i16, ptr %arrayidx127.2, align 2 + %conv128.2 = zext i16 %1 to i32 + %2 = extractelement <2 x i64> %v, i32 0 + %arrayidx127.3 = getelementptr i16, ptr %p, i64 %2 + %3 = load i16, ptr %arrayidx127.3, align 2 + %conv128.3 = zext i16 %3 to i32 + %4 = insertelement <4 x i32> zeroinitializer, i32 %conv128.2, i32 0 + %5 = insertelement <4 x i32> %4, i32 %conv128.3, i32 1 + ret <4 x i32> %5 +} -- GitLab From 2bde13cda1e389599413132028731f18fb5c03c3 Mon Sep 17 00:00:00 2001 From: Matheus Izvekov Date: Wed, 22 May 2024 12:18:44 -0300 Subject: [PATCH 137/452] [clang] NFCI: use TemplateArgumentLoc for NTTP DefaultArgument (#92852) This is an enabler for https://github.com/llvm/llvm-project/pull/92855 This allows an NTTP default argument to be set as an arbitrary TemplateArgument, not just an expression. This allows template parameter packs to have default arguments in the AST, even though the language proper doesn't support the syntax for it. This allows NTTP default arguments to be other kinds of arguments, like packs, integral constants, and such. --- clang-tools-extra/clangd/Hover.cpp | 3 +- clang/include/clang/AST/ASTNodeTraverser.h | 6 +-- clang/include/clang/AST/DeclTemplate.h | 11 +++-- clang/include/clang/AST/RecursiveASTVisitor.h | 2 +- clang/lib/AST/ASTContext.cpp | 6 ++- clang/lib/AST/ASTDiagnostic.cpp | 2 +- clang/lib/AST/ASTImporter.cpp | 5 +- clang/lib/AST/DeclPrinter.cpp | 4 +- clang/lib/AST/DeclTemplate.cpp | 15 ++++-- clang/lib/AST/JSONNodeDumper.cpp | 2 +- clang/lib/AST/ODRDiagsEmitter.cpp | 7 ++- clang/lib/AST/ODRHash.cpp | 2 +- clang/lib/AST/TypePrinter.cpp | 5 +- clang/lib/ExtractAPI/DeclarationFragments.cpp | 5 +- clang/lib/Index/IndexDecl.cpp | 3 +- clang/lib/Sema/HLSLExternalSemaSource.cpp | 10 ++-- clang/lib/Sema/SemaTemplate.cpp | 46 +++++++++---------- clang/lib/Sema/SemaTemplateDeduction.cpp | 10 ++-- .../lib/Sema/SemaTemplateInstantiateDecl.cpp | 7 +-- clang/lib/Serialization/ASTReaderDecl.cpp | 3 +- clang/lib/Serialization/ASTWriterDecl.cpp | 2 +- clang/test/AST/ast-dump-decl.cpp | 4 +- clang/test/SemaTemplate/deduction-guide.cpp | 6 +-- clang/tools/libclang/CIndex.cpp | 5 +- clang/unittests/AST/ASTImporterTest.cpp | 2 +- 25 files changed, 99 insertions(+), 74 deletions(-) diff --git a/clang-tools-extra/clangd/Hover.cpp b/clang-tools-extra/clangd/Hover.cpp index 2ec0994e846e..de103e011c70 100644 --- a/clang-tools-extra/clangd/Hover.cpp +++ b/clang-tools-extra/clangd/Hover.cpp @@ -262,7 +262,8 @@ fetchTemplateParameters(const TemplateParameterList *Params, if (NTTP->hasDefaultArgument()) { P.Default.emplace(); llvm::raw_string_ostream Out(*P.Default); - NTTP->getDefaultArgument()->printPretty(Out, nullptr, PP); + NTTP->getDefaultArgument().getArgument().print(PP, Out, + /*IncludeType=*/false); } } else if (const auto *TTPD = dyn_cast(Param)) { P.Type = printType(TTPD, PP); diff --git a/clang/include/clang/AST/ASTNodeTraverser.h b/clang/include/clang/AST/ASTNodeTraverser.h index 98db1cb57899..616f92691ec3 100644 --- a/clang/include/clang/AST/ASTNodeTraverser.h +++ b/clang/include/clang/AST/ASTNodeTraverser.h @@ -704,9 +704,9 @@ public: if (const auto *E = D->getPlaceholderTypeConstraint()) Visit(E); if (D->hasDefaultArgument()) - Visit(D->getDefaultArgument(), SourceRange(), - D->getDefaultArgStorage().getInheritedFrom(), - D->defaultArgumentWasInherited() ? "inherited from" : "previous"); + dumpTemplateArgumentLoc( + D->getDefaultArgument(), D->getDefaultArgStorage().getInheritedFrom(), + D->defaultArgumentWasInherited() ? "inherited from" : "previous"); } void VisitTemplateTemplateParmDecl(const TemplateTemplateParmDecl *D) { diff --git a/clang/include/clang/AST/DeclTemplate.h b/clang/include/clang/AST/DeclTemplate.h index 07b08b5ed43c..5b6a6b40b28e 100644 --- a/clang/include/clang/AST/DeclTemplate.h +++ b/clang/include/clang/AST/DeclTemplate.h @@ -1360,7 +1360,8 @@ class NonTypeTemplateParmDecl final /// The default template argument, if any, and whether or not /// it was inherited. - using DefArgStorage = DefaultArgStorage; + using DefArgStorage = + DefaultArgStorage; DefArgStorage DefaultArgument; // FIXME: Collapse this into TemplateParamPosition; or, just move depth/index @@ -1430,7 +1431,10 @@ public: bool hasDefaultArgument() const { return DefaultArgument.isSet(); } /// Retrieve the default argument, if any. - Expr *getDefaultArgument() const { return DefaultArgument.get(); } + const TemplateArgumentLoc &getDefaultArgument() const { + static const TemplateArgumentLoc NoneLoc; + return DefaultArgument.isSet() ? *DefaultArgument.get() : NoneLoc; + } /// Retrieve the location of the default argument, if any. SourceLocation getDefaultArgumentLoc() const; @@ -1444,7 +1448,8 @@ public: /// Set the default argument for this template parameter, and /// whether that default argument was inherited from another /// declaration. - void setDefaultArgument(Expr *DefArg) { DefaultArgument.set(DefArg); } + void setDefaultArgument(const ASTContext &C, + const TemplateArgumentLoc &DefArg); void setInheritedDefaultArgument(const ASTContext &C, NonTypeTemplateParmDecl *Parm) { DefaultArgument.setInherited(C, Parm); diff --git a/clang/include/clang/AST/RecursiveASTVisitor.h b/clang/include/clang/AST/RecursiveASTVisitor.h index 659e4cdd1037..a4b8d6ef61d5 100644 --- a/clang/include/clang/AST/RecursiveASTVisitor.h +++ b/clang/include/clang/AST/RecursiveASTVisitor.h @@ -2320,7 +2320,7 @@ DEF_TRAVERSE_DECL(NonTypeTemplateParmDecl, { // A non-type template parameter, e.g. "S" in template class Foo ... TRY_TO(TraverseDeclaratorHelper(D)); if (D->hasDefaultArgument() && !D->defaultArgumentWasInherited()) - TRY_TO(TraverseStmt(D->getDefaultArgument())); + TRY_TO(TraverseTemplateArgumentLoc(D->getDefaultArgument())); }) DEF_TRAVERSE_DECL(ParmVarDecl, { diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp index f9902a978aa3..a2398fef623e 100644 --- a/clang/lib/AST/ASTContext.cpp +++ b/clang/lib/AST/ASTContext.cpp @@ -6503,8 +6503,10 @@ bool ASTContext::isSameDefaultTemplateArgument(const NamedDecl *X, if (!NTTPX->hasDefaultArgument() || !NTTPY->hasDefaultArgument()) return false; - Expr *DefaultArgumentX = NTTPX->getDefaultArgument()->IgnoreImpCasts(); - Expr *DefaultArgumentY = NTTPY->getDefaultArgument()->IgnoreImpCasts(); + Expr *DefaultArgumentX = + NTTPX->getDefaultArgument().getArgument().getAsExpr()->IgnoreImpCasts(); + Expr *DefaultArgumentY = + NTTPY->getDefaultArgument().getArgument().getAsExpr()->IgnoreImpCasts(); llvm::FoldingSetNodeID XID, YID; DefaultArgumentX->Profile(XID, *this, /*Canonical=*/true); DefaultArgumentY->Profile(YID, *this, /*Canonical=*/true); diff --git a/clang/lib/AST/ASTDiagnostic.cpp b/clang/lib/AST/ASTDiagnostic.cpp index 7b0d5f9cc1a9..91bc1b22acfc 100644 --- a/clang/lib/AST/ASTDiagnostic.cpp +++ b/clang/lib/AST/ASTDiagnostic.cpp @@ -1238,7 +1238,7 @@ class TemplateDiff { E = Iter->getAsExpr(); } } else if (!Default->isParameterPack()) { - E = Default->getDefaultArgument(); + E = Default->getDefaultArgument().getArgument().getAsExpr(); } if (!Iter.hasDesugaredTA()) return; diff --git a/clang/lib/AST/ASTImporter.cpp b/clang/lib/AST/ASTImporter.cpp index a47dd72a5679..cab5ee604795 100644 --- a/clang/lib/AST/ASTImporter.cpp +++ b/clang/lib/AST/ASTImporter.cpp @@ -5949,10 +5949,11 @@ ASTNodeImporter::VisitNonTypeTemplateParmDecl(NonTypeTemplateParmDecl *D) { return ToD; if (D->hasDefaultArgument()) { - ExpectedExpr ToDefaultArgOrErr = import(D->getDefaultArgument()); + Expected ToDefaultArgOrErr = + import(D->getDefaultArgument()); if (!ToDefaultArgOrErr) return ToDefaultArgOrErr.takeError(); - ToD->setDefaultArgument(*ToDefaultArgOrErr); + ToD->setDefaultArgument(Importer.getToContext(), *ToDefaultArgOrErr); } return ToD; diff --git a/clang/lib/AST/DeclPrinter.cpp b/clang/lib/AST/DeclPrinter.cpp index bf32aafc3d0a..0cf4e64f83b8 100644 --- a/clang/lib/AST/DeclPrinter.cpp +++ b/clang/lib/AST/DeclPrinter.cpp @@ -1898,7 +1898,7 @@ void DeclPrinter::VisitNonTypeTemplateParmDecl( if (NTTP->hasDefaultArgument()) { Out << " = "; - NTTP->getDefaultArgument()->printPretty(Out, nullptr, Policy, Indentation, - "\n", &Context); + NTTP->getDefaultArgument().getArgument().print(Policy, Out, + /*IncludeType=*/false); } } diff --git a/clang/lib/AST/DeclTemplate.cpp b/clang/lib/AST/DeclTemplate.cpp index 46bb3e8e5138..95ffd4784641 100644 --- a/clang/lib/AST/DeclTemplate.cpp +++ b/clang/lib/AST/DeclTemplate.cpp @@ -795,14 +795,21 @@ NonTypeTemplateParmDecl::CreateDeserialized(ASTContext &C, GlobalDeclID ID, SourceRange NonTypeTemplateParmDecl::getSourceRange() const { if (hasDefaultArgument() && !defaultArgumentWasInherited()) return SourceRange(getOuterLocStart(), - getDefaultArgument()->getSourceRange().getEnd()); + getDefaultArgument().getSourceRange().getEnd()); return DeclaratorDecl::getSourceRange(); } SourceLocation NonTypeTemplateParmDecl::getDefaultArgumentLoc() const { - return hasDefaultArgument() - ? getDefaultArgument()->getSourceRange().getBegin() - : SourceLocation(); + return hasDefaultArgument() ? getDefaultArgument().getSourceRange().getBegin() + : SourceLocation(); +} + +void NonTypeTemplateParmDecl::setDefaultArgument( + const ASTContext &C, const TemplateArgumentLoc &DefArg) { + if (DefArg.getArgument().isNull()) + DefaultArgument.set(nullptr); + else + DefaultArgument.set(new (C) TemplateArgumentLoc(DefArg)); } //===----------------------------------------------------------------------===// diff --git a/clang/lib/AST/JSONNodeDumper.cpp b/clang/lib/AST/JSONNodeDumper.cpp index efd3a639d746..3bbb3a905e9b 100644 --- a/clang/lib/AST/JSONNodeDumper.cpp +++ b/clang/lib/AST/JSONNodeDumper.cpp @@ -1044,7 +1044,7 @@ void JSONNodeDumper::VisitNonTypeTemplateParmDecl( if (D->hasDefaultArgument()) JOS.attributeObject("defaultArg", [=] { - Visit(D->getDefaultArgument(), SourceRange(), + Visit(D->getDefaultArgument().getArgument(), SourceRange(), D->getDefaultArgStorage().getInheritedFrom(), D->defaultArgumentWasInherited() ? "inherited from" : "previous"); }); diff --git a/clang/lib/AST/ODRDiagsEmitter.cpp b/clang/lib/AST/ODRDiagsEmitter.cpp index 97b6c14d9ede..37f0f68c9235 100644 --- a/clang/lib/AST/ODRDiagsEmitter.cpp +++ b/clang/lib/AST/ODRDiagsEmitter.cpp @@ -1523,8 +1523,11 @@ bool ODRDiagsEmitter::diagnoseMismatch( } if (HasFirstDefaultArgument && HasSecondDefaultArgument) { - Expr *FirstDefaultArgument = FirstNTTPD->getDefaultArgument(); - Expr *SecondDefaultArgument = SecondNTTPD->getDefaultArgument(); + TemplateArgument FirstDefaultArgument = + FirstNTTPD->getDefaultArgument().getArgument(); + TemplateArgument SecondDefaultArgument = + SecondNTTPD->getDefaultArgument().getArgument(); + if (computeODRHash(FirstDefaultArgument) != computeODRHash(SecondDefaultArgument)) { DiagTemplateError(FunctionTemplateParameterDifferentDefaultArgument) diff --git a/clang/lib/AST/ODRHash.cpp b/clang/lib/AST/ODRHash.cpp index 18b1e17e0fee..246e56231539 100644 --- a/clang/lib/AST/ODRHash.cpp +++ b/clang/lib/AST/ODRHash.cpp @@ -480,7 +480,7 @@ public: D->hasDefaultArgument() && !D->defaultArgumentWasInherited(); Hash.AddBoolean(hasDefaultArgument); if (hasDefaultArgument) { - AddStmt(D->getDefaultArgument()); + AddTemplateArgument(D->getDefaultArgument().getArgument()); } Hash.AddBoolean(D->isParameterPack()); diff --git a/clang/lib/AST/TypePrinter.cpp b/clang/lib/AST/TypePrinter.cpp index 981f09410401..5ed56b367a46 100644 --- a/clang/lib/AST/TypePrinter.cpp +++ b/clang/lib/AST/TypePrinter.cpp @@ -2281,8 +2281,9 @@ bool clang::isSubstitutedDefaultArgument(ASTContext &Ctx, TemplateArgument Arg, Ctx, Arg, TTPD->getDefaultArgument().getArgument(), Args, Depth); } else if (auto *NTTPD = dyn_cast(Param)) { return NTTPD->hasDefaultArgument() && - isSubstitutedTemplateArgument(Ctx, Arg, NTTPD->getDefaultArgument(), - Args, Depth); + isSubstitutedTemplateArgument( + Ctx, Arg, NTTPD->getDefaultArgument().getArgument(), Args, + Depth); } return false; } diff --git a/clang/lib/ExtractAPI/DeclarationFragments.cpp b/clang/lib/ExtractAPI/DeclarationFragments.cpp index d88e4e0df8ef..904b9315f26e 100644 --- a/clang/lib/ExtractAPI/DeclarationFragments.cpp +++ b/clang/lib/ExtractAPI/DeclarationFragments.cpp @@ -1023,8 +1023,9 @@ DeclarationFragmentsBuilder::getFragmentsForTemplateParameters( if (NTP->hasDefaultArgument()) { SmallString<8> ExprStr; raw_svector_ostream Output(ExprStr); - NTP->getDefaultArgument()->printPretty( - Output, nullptr, NTP->getASTContext().getPrintingPolicy()); + NTP->getDefaultArgument().getArgument().print( + NTP->getASTContext().getPrintingPolicy(), Output, + /*IncludeType=*/false); Fragments.append(" = ", DeclarationFragments::FragmentKind::Text) .append(ExprStr, DeclarationFragments::FragmentKind::Text); } diff --git a/clang/lib/Index/IndexDecl.cpp b/clang/lib/Index/IndexDecl.cpp index 058f4aef918a..a7fa6c5e6898 100644 --- a/clang/lib/Index/IndexDecl.cpp +++ b/clang/lib/Index/IndexDecl.cpp @@ -711,7 +711,8 @@ public: } else if (const auto *NTTP = dyn_cast(TP)) { IndexCtx.indexTypeSourceInfo(NTTP->getTypeSourceInfo(), Parent); if (NTTP->hasDefaultArgument()) - IndexCtx.indexBody(NTTP->getDefaultArgument(), Parent); + handleTemplateArgumentLoc(NTTP->getDefaultArgument(), Parent, + TP->getLexicalDeclContext()); } else if (const auto *TTPD = dyn_cast(TP)) { if (TTPD->hasDefaultArgument()) handleTemplateArgumentLoc(TTPD->getDefaultArgument(), Parent, diff --git a/clang/lib/Sema/HLSLExternalSemaSource.cpp b/clang/lib/Sema/HLSLExternalSemaSource.cpp index fa8c852ea9e9..a2b29a7bdf50 100644 --- a/clang/lib/Sema/HLSLExternalSemaSource.cpp +++ b/clang/lib/Sema/HLSLExternalSemaSource.cpp @@ -442,10 +442,12 @@ void HLSLExternalSemaSource::defineHLSLVectorAlias() { AST, HLSLNamespace, SourceLocation(), SourceLocation(), 0, 1, &AST.Idents.get("element_count", tok::TokenKind::identifier), AST.IntTy, false, AST.getTrivialTypeSourceInfo(AST.IntTy)); - Expr *LiteralExpr = - IntegerLiteral::Create(AST, llvm::APInt(AST.getIntWidth(AST.IntTy), 4), - AST.IntTy, SourceLocation()); - SizeParam->setDefaultArgument(LiteralExpr); + llvm::APInt Val(AST.getIntWidth(AST.IntTy), 4); + TemplateArgument Default(AST, llvm::APSInt(std::move(Val)), AST.IntTy, + /*IsDefaulted=*/true); + SizeParam->setDefaultArgument( + AST, SemaPtr->getTrivialTemplateArgumentLoc(Default, AST.IntTy, + SourceLocation(), SizeParam)); TemplateParams.emplace_back(SizeParam); auto *ParamList = diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp index f930bd8651d5..39e9dbed0c3e 100644 --- a/clang/lib/Sema/SemaTemplate.cpp +++ b/clang/lib/Sema/SemaTemplate.cpp @@ -1599,7 +1599,9 @@ NamedDecl *Sema::ActOnNonTypeTemplateParameter(Scope *S, Declarator &D, if (DiagnoseUnexpandedParameterPack(Default, UPPC_DefaultArgument)) return Param; - Param->setDefaultArgument(Default); + Param->setDefaultArgument( + Context, getTrivialTemplateArgumentLoc(TemplateArgument(Default), + QualType(), SourceLocation())); } return Param; @@ -3630,9 +3632,9 @@ bool Sema::CheckTemplateParameterList(TemplateParameterList *NewParams, // Check the presence of a default argument here. if (NewNonTypeParm->hasDefaultArgument() && - DiagnoseDefaultTemplateArgument(*this, TPC, - NewNonTypeParm->getLocation(), - NewNonTypeParm->getDefaultArgument()->getSourceRange())) { + DiagnoseDefaultTemplateArgument( + *this, TPC, NewNonTypeParm->getLocation(), + NewNonTypeParm->getDefaultArgument().getSourceRange())) { NewNonTypeParm->removeDefaultArgument(); } @@ -6107,16 +6109,17 @@ static bool SubstDefaultTemplateArgument( /// parameters that precede \p Param in the template parameter list. /// /// \returns the substituted template argument, or NULL if an error occurred. -static ExprResult SubstDefaultTemplateArgument( +static bool SubstDefaultTemplateArgument( Sema &SemaRef, TemplateDecl *Template, SourceLocation TemplateLoc, SourceLocation RAngleLoc, NonTypeTemplateParmDecl *Param, ArrayRef SugaredConverted, - ArrayRef CanonicalConverted) { + ArrayRef CanonicalConverted, + TemplateArgumentLoc &Output) { Sema::InstantiatingTemplate Inst(SemaRef, TemplateLoc, Param, Template, SugaredConverted, SourceRange(TemplateLoc, RAngleLoc)); if (Inst.isInvalid()) - return ExprError(); + return true; // Only substitute for the innermost template argument list. MultiLevelTemplateArgumentList TemplateArgLists(Template, SugaredConverted, @@ -6127,7 +6130,8 @@ static ExprResult SubstDefaultTemplateArgument( Sema::ContextRAII SavedContext(SemaRef, Template->getDeclContext()); EnterExpressionEvaluationContext ConstantEvaluated( SemaRef, Sema::ExpressionEvaluationContext::ConstantEvaluated); - return SemaRef.SubstExpr(Param->getDefaultArgument(), TemplateArgLists); + return SemaRef.SubstTemplateArgument(Param->getDefaultArgument(), + TemplateArgLists, Output); } /// Substitute template arguments into the default template argument for @@ -6219,14 +6223,12 @@ TemplateArgumentLoc Sema::SubstDefaultTemplateArgumentIfAvailable( return TemplateArgumentLoc(); HasDefaultArg = true; - ExprResult Arg = SubstDefaultTemplateArgument( - *this, Template, TemplateLoc, RAngleLoc, NonTypeParm, SugaredConverted, - CanonicalConverted); - if (Arg.isInvalid()) + TemplateArgumentLoc Output; + if (SubstDefaultTemplateArgument(*this, Template, TemplateLoc, RAngleLoc, + NonTypeParm, SugaredConverted, + CanonicalConverted, Output)) return TemplateArgumentLoc(); - - Expr *ArgE = Arg.getAs(); - return TemplateArgumentLoc(TemplateArgument(ArgE), ArgE); + return Output; } TemplateTemplateParmDecl *TempTempParm @@ -6803,14 +6805,10 @@ bool Sema::CheckTemplateArgumentList( return diagnoseMissingArgument(*this, TemplateLoc, Template, NTTP, NewArgs); - ExprResult E = SubstDefaultTemplateArgument( - *this, Template, TemplateLoc, RAngleLoc, NTTP, SugaredConverted, - CanonicalConverted); - if (E.isInvalid()) + if (SubstDefaultTemplateArgument(*this, Template, TemplateLoc, RAngleLoc, + NTTP, SugaredConverted, + CanonicalConverted, Arg)) return true; - - Expr *Ex = E.getAs(); - Arg = TemplateArgumentLoc(TemplateArgument(Ex), Ex); } else { TemplateTemplateParmDecl *TempParm = cast(*Param); @@ -9523,10 +9521,10 @@ DeclResult Sema::ActOnClassTemplateSpecialization( } } else if (NonTypeTemplateParmDecl *NTTP = dyn_cast(Param)) { - if (Expr *DefArg = NTTP->getDefaultArgument()) { + if (NTTP->hasDefaultArgument()) { Diag(NTTP->getDefaultArgumentLoc(), diag::err_default_arg_in_partial_spec) - << DefArg->getSourceRange(); + << NTTP->getDefaultArgument().getSourceRange(); NTTP->removeDefaultArgument(); } } else { diff --git a/clang/lib/Sema/SemaTemplateDeduction.cpp b/clang/lib/Sema/SemaTemplateDeduction.cpp index 0c348633576d..f16a07e1a1b3 100644 --- a/clang/lib/Sema/SemaTemplateDeduction.cpp +++ b/clang/lib/Sema/SemaTemplateDeduction.cpp @@ -536,14 +536,14 @@ static NamedDecl *getTemplateParameterWithDefault(Sema &S, NamedDecl *A, } case Decl::NonTypeTemplateParm: { auto *T = cast(A); - // FIXME: Ditto, as above for TemplateTypeParm case. - if (T->isParameterPack()) - return A; auto *R = NonTypeTemplateParmDecl::Create( S.Context, A->getDeclContext(), SourceLocation(), SourceLocation(), T->getDepth(), T->getIndex(), T->getIdentifier(), T->getType(), - /*ParameterPack=*/false, T->getTypeSourceInfo()); - R->setDefaultArgument(Default.getAsExpr()); + T->isParameterPack(), T->getTypeSourceInfo()); + R->setDefaultArgument(S.Context, + S.getTrivialTemplateArgumentLoc( + Default, Default.getNonTypeTemplateArgumentType(), + SourceLocation())); if (auto *PTC = T->getPlaceholderTypeConstraint()) R->setPlaceholderTypeConstraint(PTC); return R; diff --git a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp index 38a300332068..09812946bd38 100644 --- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -3123,9 +3123,10 @@ Decl *TemplateDeclInstantiator::VisitNonTypeTemplateParmDecl( if (D->hasDefaultArgument() && !D->defaultArgumentWasInherited()) { EnterExpressionEvaluationContext ConstantEvaluated( SemaRef, Sema::ExpressionEvaluationContext::ConstantEvaluated); - ExprResult Value = SemaRef.SubstExpr(D->getDefaultArgument(), TemplateArgs); - if (!Value.isInvalid()) - Param->setDefaultArgument(Value.get()); + TemplateArgumentLoc Result; + if (!SemaRef.SubstTemplateArgument(D->getDefaultArgument(), TemplateArgs, + Result)) + Param->setDefaultArgument(SemaRef.Context, Result); } // Introduce this template parameter's instantiation into the instantiation diff --git a/clang/lib/Serialization/ASTReaderDecl.cpp b/clang/lib/Serialization/ASTReaderDecl.cpp index d7a9e31b477f..61cc99d4df68 100644 --- a/clang/lib/Serialization/ASTReaderDecl.cpp +++ b/clang/lib/Serialization/ASTReaderDecl.cpp @@ -2717,7 +2717,8 @@ void ASTDeclReader::VisitNonTypeTemplateParmDecl(NonTypeTemplateParmDecl *D) { // Rest of NonTypeTemplateParmDecl. D->ParameterPack = Record.readInt(); if (Record.readInt()) - D->setDefaultArgument(Record.readExpr()); + D->setDefaultArgument(Reader.getContext(), + Record.readTemplateArgumentLoc()); } } diff --git a/clang/lib/Serialization/ASTWriterDecl.cpp b/clang/lib/Serialization/ASTWriterDecl.cpp index b2a214e935aa..bbd16dbdb8ff 100644 --- a/clang/lib/Serialization/ASTWriterDecl.cpp +++ b/clang/lib/Serialization/ASTWriterDecl.cpp @@ -1941,7 +1941,7 @@ void ASTDeclWriter::VisitNonTypeTemplateParmDecl(NonTypeTemplateParmDecl *D) { !D->defaultArgumentWasInherited(); Record.push_back(OwnsDefaultArg); if (OwnsDefaultArg) - Record.AddStmt(D->getDefaultArgument()); + Record.AddTemplateArgumentLoc(D->getDefaultArgument()); Code = serialization::DECL_NON_TYPE_TEMPLATE_PARM; } } diff --git a/clang/test/AST/ast-dump-decl.cpp b/clang/test/AST/ast-dump-decl.cpp index 554cdcf83fcd..e062d4f068a4 100644 --- a/clang/test/AST/ast-dump-decl.cpp +++ b/clang/test/AST/ast-dump-decl.cpp @@ -459,7 +459,7 @@ namespace testClassTemplateDecl { // CHECK: ClassTemplateDecl 0x{{.+}} <{{.+}}:[[@LINE-148]]:3, col:31> col:31 TestTemplateDefaultNonType{{$}} // CHECK-NEXT: |-NonTypeTemplateParmDecl 0x{{.+}} col:16 'int' depth 0 index 0 I{{$}} -// CHECK-NEXT: | `-TemplateArgument expr{{$}} +// CHECK-NEXT: | `-TemplateArgument expr{{$}} // CHECK-NEXT: | `-IntegerLiteral 0x{{.+}} 'int' 42{{$}} // CHECK-NEXT: `-CXXRecordDecl 0x{{.+}} col:31 struct TestTemplateDefaultNonType{{$}} @@ -671,7 +671,7 @@ namespace TestNonTypeTemplateParmDecl { // CHECK: NamespaceDecl{{.*}} TestNonTypeTemplateParmDecl // CHECK-NEXT: FunctionTemplateDecl // CHECK-NEXT: NonTypeTemplateParmDecl{{.*}} 'int' depth 0 index 0 I -// CHECK-NEXT: TemplateArgument expr +// CHECK-NEXT: TemplateArgument {{.*}} expr // CHECK-NEXT: IntegerLiteral{{.*}} 'int' 1 // CHECK-NEXT: NonTypeTemplateParmDecl{{.*}} 'int' depth 0 index 1 ... J diff --git a/clang/test/SemaTemplate/deduction-guide.cpp b/clang/test/SemaTemplate/deduction-guide.cpp index a91ab5ec7bcc..0eaeb49e6b32 100644 --- a/clang/test/SemaTemplate/deduction-guide.cpp +++ b/clang/test/SemaTemplate/deduction-guide.cpp @@ -100,7 +100,7 @@ using CT = C; // CHECK: | `-NonTypeTemplateParmDecl {{.*}} 'X' depth 1 index 1 // CHECK: |-TemplateTypeParmDecl {{.*}} typename depth 0 index 2 U // CHECK: |-NonTypeTemplateParmDecl {{.*}} 'type-parameter-0-2' depth 0 index 3 V -// CHECK: | `-TemplateArgument expr +// CHECK: | `-TemplateArgument {{.*}} expr // CHECK: | `-IntegerLiteral {{.*}} 'int' 0 // CHECK: |-CXXDeductionGuideDecl {{.*}} 'auto (A, Y<>, type-parameter-0-2) -> C' // CHECK: | |-ParmVarDecl {{.*}} 'A' @@ -139,7 +139,7 @@ using DT = D; // CHECK: |-TemplateTypeParmDecl {{.*}} typename depth 0 index 0 ... T // CHECK: |-TemplateTypeParmDecl {{.*}} typename depth 0 index 1 U1 // CHECK: |-TemplateTypeParmDecl {{.*}} typename depth 0 index 2 U2 -// CHECK: `-CXXDeductionGuideDecl {{.*}} 'auto (B *) -> D' +// CHECK: `-CXXDeductionGuideDecl {{.*}} 'auto (B *) -> D' // CHECK: `-ParmVarDecl {{.*}} 'B *' // CHECK: FunctionProtoType {{.*}} 'auto (B *) -> D' dependent trailing_return // CHECK: |-InjectedClassNameType {{.*}} 'D' dependent @@ -222,7 +222,7 @@ F s(0); // CHECK-LABEL: Dumping : // CHECK: FunctionTemplateDecl // CHECK: |-NonTypeTemplateParmDecl {{.*}} 'char' depth 0 index 0 -// CHECK: `-TemplateArgument expr +// CHECK: `-TemplateArgument {{.*}} expr // CHECK: | |-inherited from NonTypeTemplateParm {{.*}} '' 'char' // CHECK: | `-CharacterLiteral {{.*}} 'char' 120 // CHECK: |-TemplateTypeParmDecl {{.*}} typename depth 0 index 1 U diff --git a/clang/tools/libclang/CIndex.cpp b/clang/tools/libclang/CIndex.cpp index d0d654568d84..49ed60d990ca 100644 --- a/clang/tools/libclang/CIndex.cpp +++ b/clang/tools/libclang/CIndex.cpp @@ -945,8 +945,9 @@ bool CursorVisitor::VisitNonTypeTemplateParmDecl(NonTypeTemplateParmDecl *D) { return true; if (D->hasDefaultArgument() && !D->defaultArgumentWasInherited()) - if (Expr *DefArg = D->getDefaultArgument()) - return Visit(MakeCXCursor(DefArg, StmtParent, TU, RegionOfInterest)); + if (D->hasDefaultArgument() && + VisitTemplateArgumentLoc(D->getDefaultArgument())) + return true; return false; } diff --git a/clang/unittests/AST/ASTImporterTest.cpp b/clang/unittests/AST/ASTImporterTest.cpp index ba630002c055..3dc1c336365d 100644 --- a/clang/unittests/AST/ASTImporterTest.cpp +++ b/clang/unittests/AST/ASTImporterTest.cpp @@ -1260,7 +1260,7 @@ TEST_P(ASTImporterOptionSpecificTestBase, NonTypeTemplateParmDeclDefaultArg) { FromTU, nonTypeTemplateParmDecl(hasName("S"))); NonTypeTemplateParmDecl *To = Import(From, Lang_CXX03); ASSERT_TRUE(To->hasDefaultArgument()); - Stmt *ToArg = To->getDefaultArgument(); + Stmt *ToArg = To->getDefaultArgument().getArgument().getAsExpr(); ASSERT_TRUE(isa(ToArg)); ASSERT_EQ(cast(ToArg)->getValue().getLimitedValue(), 1U); } -- GitLab From cb6a62369a353f506a1dde087eeaf5ebea5d5c26 Mon Sep 17 00:00:00 2001 From: Thomas Symalla <5754458+tsymalla@users.noreply.github.com> Date: Wed, 22 May 2024 17:23:50 +0200 Subject: [PATCH 138/452] Add `AddNull` argument to `CreateGlobalString`. (#93036) There's currently no way to control whether a null terminator should be appended to the string created in `CreateGlobalString` / `CreateGlobalStringPtr`, since the methods don't expose an additional argument. This change adds an additional argument to the methods that has the same default value, `true`, as in `ConstantDataArray::getString`, and passes it down to this internal method. --- llvm/include/llvm/IR/IRBuilder.h | 7 ++++--- llvm/lib/IR/IRBuilder.cpp | 4 ++-- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/llvm/include/llvm/IR/IRBuilder.h b/llvm/include/llvm/IR/IRBuilder.h index 0d8746344a44..40a9cf507248 100644 --- a/llvm/include/llvm/IR/IRBuilder.h +++ b/llvm/include/llvm/IR/IRBuilder.h @@ -455,7 +455,7 @@ public: /// block. GlobalVariable *CreateGlobalString(StringRef Str, const Twine &Name = "", unsigned AddressSpace = 0, - Module *M = nullptr); + Module *M = nullptr, bool AddNull = true); /// Get a constant value representing either true or false. ConstantInt *getInt1(bool V) { @@ -1992,8 +1992,9 @@ public: /// block. Constant *CreateGlobalStringPtr(StringRef Str, const Twine &Name = "", unsigned AddressSpace = 0, - Module *M = nullptr) { - GlobalVariable *GV = CreateGlobalString(Str, Name, AddressSpace, M); + Module *M = nullptr, bool AddNull = true) { + GlobalVariable *GV = + CreateGlobalString(Str, Name, AddressSpace, M, AddNull); Constant *Zero = ConstantInt::get(Type::getInt32Ty(Context), 0); Constant *Indices[] = {Zero, Zero}; return ConstantExpr::getInBoundsGetElementPtr(GV->getValueType(), GV, diff --git a/llvm/lib/IR/IRBuilder.cpp b/llvm/lib/IR/IRBuilder.cpp index 0d6760ed0841..b32799355d69 100644 --- a/llvm/lib/IR/IRBuilder.cpp +++ b/llvm/lib/IR/IRBuilder.cpp @@ -43,8 +43,8 @@ using namespace llvm; GlobalVariable *IRBuilderBase::CreateGlobalString(StringRef Str, const Twine &Name, unsigned AddressSpace, - Module *M) { - Constant *StrConstant = ConstantDataArray::getString(Context, Str); + Module *M, bool AddNull) { + Constant *StrConstant = ConstantDataArray::getString(Context, Str, AddNull); if (!M) M = BB->getParent()->getParent(); auto *GV = new GlobalVariable( -- GitLab From 5b205956e16e09af117c45e2eab625fce7a05b95 Mon Sep 17 00:00:00 2001 From: Han-Kuan Chen Date: Wed, 22 May 2024 23:26:33 +0800 Subject: [PATCH 139/452] [SLP] NFC. Reduce newTreeEntry usage. (#92994) --- .../Transforms/Vectorize/SLPVectorizer.cpp | 47 ++++++------------- 1 file changed, 15 insertions(+), 32 deletions(-) diff --git a/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp b/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp index 77bb6e9a6a9b..339b3c2b5f91 100644 --- a/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp +++ b/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp @@ -6861,23 +6861,16 @@ void BoUpSLP::buildTree_rec(ArrayRef VL, unsigned Depth, case Instruction::ExtractElement: { if (CurrentOrder.empty()) { LLVM_DEBUG(dbgs() << "SLP: Reusing or shuffling extract sequence.\n"); - newTreeEntry(VL, Bundle /*vectorized*/, S, UserTreeIdx, - ReuseShuffleIndices); - // This is a special case, as it does not gather, but at the same time - // we are not extending buildTree_rec() towards the operands. - ValueList Op0; - Op0.assign(VL.size(), VL0->getOperand(0)); - VectorizableTree.back()->setOperand(0, Op0); - return; + } else { + LLVM_DEBUG({ + dbgs() << "SLP: Reusing or shuffling of reordered extract sequence " + "with order"; + for (unsigned Idx : CurrentOrder) + dbgs() << " " << Idx; + dbgs() << "\n"; + }); + fixupOrderingIndices(CurrentOrder); } - LLVM_DEBUG({ - dbgs() << "SLP: Reusing or shuffling of reordered extract sequence " - "with order"; - for (unsigned Idx : CurrentOrder) - dbgs() << " " << Idx; - dbgs() << "\n"; - }); - fixupOrderingIndices(CurrentOrder); // Insert new order with initial value 0, if it does not exist, // otherwise return the iterator to the existing one. newTreeEntry(VL, Bundle /*vectorized*/, S, UserTreeIdx, @@ -6931,28 +6924,18 @@ void BoUpSLP::buildTree_rec(ArrayRef VL, unsigned Depth, fixupOrderingIndices(CurrentOrder); switch (State) { case TreeEntry::Vectorize: - if (CurrentOrder.empty()) { - // Original loads are consecutive and does not require reordering. - TE = newTreeEntry(VL, Bundle /*vectorized*/, S, UserTreeIdx, - ReuseShuffleIndices); + TE = newTreeEntry(VL, Bundle /*vectorized*/, S, UserTreeIdx, + ReuseShuffleIndices, CurrentOrder); + if (CurrentOrder.empty()) LLVM_DEBUG(dbgs() << "SLP: added a vector of loads.\n"); - } else { - // Need to reorder. - TE = newTreeEntry(VL, Bundle /*vectorized*/, S, UserTreeIdx, - ReuseShuffleIndices, CurrentOrder); + else LLVM_DEBUG(dbgs() << "SLP: added a vector of jumbled loads.\n"); - } TE->setOperandsInOrder(); break; case TreeEntry::StridedVectorize: // Vectorizing non-consecutive loads with `llvm.masked.gather`. - if (CurrentOrder.empty()) { - TE = newTreeEntry(VL, TreeEntry::StridedVectorize, Bundle, S, - UserTreeIdx, ReuseShuffleIndices); - } else { - TE = newTreeEntry(VL, TreeEntry::StridedVectorize, Bundle, S, - UserTreeIdx, ReuseShuffleIndices, CurrentOrder); - } + TE = newTreeEntry(VL, TreeEntry::StridedVectorize, Bundle, S, + UserTreeIdx, ReuseShuffleIndices, CurrentOrder); TE->setOperandsInOrder(); LLVM_DEBUG(dbgs() << "SLP: added a vector of strided loads.\n"); break; -- GitLab From 3c67c227f2e16accd3cdb3aeb4c845edabd2f6c4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timm=20B=C3=A4der?= Date: Wed, 22 May 2024 14:35:43 +0200 Subject: [PATCH 140/452] [clang][Interp] Test non-active union access --- clang/lib/AST/Interp/Interp.cpp | 4 ++-- clang/test/AST/Interp/unions.cpp | 6 ++---- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/clang/lib/AST/Interp/Interp.cpp b/clang/lib/AST/Interp/Interp.cpp index 1ed2ff30bdd0..cac678352e2c 100644 --- a/clang/lib/AST/Interp/Interp.cpp +++ b/clang/lib/AST/Interp/Interp.cpp @@ -457,10 +457,10 @@ bool CheckLoad(InterpState &S, CodePtr OpPC, const Pointer &Ptr) { return false; if (!CheckRange(S, OpPC, Ptr, AK_Read)) return false; - if (!CheckInitialized(S, OpPC, Ptr, AK_Read)) - return false; if (!CheckActive(S, OpPC, Ptr, AK_Read)) return false; + if (!CheckInitialized(S, OpPC, Ptr, AK_Read)) + return false; if (!CheckTemporary(S, OpPC, Ptr, AK_Read)) return false; if (!CheckMutable(S, OpPC, Ptr)) diff --git a/clang/test/AST/Interp/unions.cpp b/clang/test/AST/Interp/unions.cpp index 08ca39c3cb08..004e500de064 100644 --- a/clang/test/AST/Interp/unions.cpp +++ b/clang/test/AST/Interp/unions.cpp @@ -1,8 +1,6 @@ // RUN: %clang_cc1 -fexperimental-new-constant-interpreter -verify=expected,both %s // RUN: %clang_cc1 -verify=ref,both %s -// both-no-diagnostics - union U { int a; int b; @@ -10,5 +8,5 @@ union U { constexpr U a = {12}; static_assert(a.a == 12, ""); - - +static_assert(a.b == 0, ""); // both-error {{not an integral constant expression}} \ + // both-note {{read of member 'b' of union with active member 'a'}} -- GitLab From 821bcba00d5c22c4a829323f8920e0f2dfc1d665 Mon Sep 17 00:00:00 2001 From: Yingwei Zheng Date: Wed, 22 May 2024 23:35:37 +0800 Subject: [PATCH 141/452] [GISel] Add narrowScalar/widenScalar support for `G_CONSTANT_FOLD_BARRIER` (#93031) Fixes an error that llc fails to legalize `G_CONSTANT_FOLD_BARRIER` with i16/i128: https://godbolt.org/z/f9n6xM3sv --- .../CodeGen/GlobalISel/LegalizerHelper.cpp | 6 +- .../RISCV/GlobalISel/constbarrier-rv32.ll | 60 +++++++++++++++++++ .../RISCV/GlobalISel/constbarrier-rv64.ll | 36 +++++++++++ .../legalizer/legalize-constbarrier-rv32.mir | 32 ++++++++++ .../legalizer/legalize-constbarrier-rv64.mir | 33 ++++++++++ 5 files changed, 165 insertions(+), 2 deletions(-) create mode 100644 llvm/test/CodeGen/RISCV/GlobalISel/constbarrier-rv32.ll create mode 100644 llvm/test/CodeGen/RISCV/GlobalISel/constbarrier-rv64.ll diff --git a/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp b/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp index 40507845d8d8..d8b0f52ecf9e 100644 --- a/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp +++ b/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp @@ -1296,7 +1296,7 @@ LegalizerHelper::LegalizeResult LegalizerHelper::narrowScalar(MachineInstr &MI, MI.eraseFromParent(); return Legalized; } - + case TargetOpcode::G_CONSTANT_FOLD_BARRIER: case TargetOpcode::G_FREEZE: { if (TypeIdx != 0) return UnableToLegalize; @@ -1310,7 +1310,8 @@ LegalizerHelper::LegalizeResult LegalizerHelper::narrowScalar(MachineInstr &MI, SmallVector Parts; for (unsigned i = 0; i < Unmerge->getNumDefs(); ++i) { Parts.push_back( - MIRBuilder.buildFreeze(NarrowTy, Unmerge.getReg(i)).getReg(0)); + MIRBuilder.buildInstr(MI.getOpcode(), {NarrowTy}, {Unmerge.getReg(i)}) + .getReg(0)); } MIRBuilder.buildMergeLikeInstr(MI.getOperand(0).getReg(), Parts); @@ -2515,6 +2516,7 @@ LegalizerHelper::widenScalar(MachineInstr &MI, unsigned TypeIdx, LLT WideTy) { return Legalized; } case TargetOpcode::G_FREEZE: + case TargetOpcode::G_CONSTANT_FOLD_BARRIER: Observer.changingInstr(MI); widenScalarSrc(MI, WideTy, 1, TargetOpcode::G_ANYEXT); widenScalarDst(MI, WideTy); diff --git a/llvm/test/CodeGen/RISCV/GlobalISel/constbarrier-rv32.ll b/llvm/test/CodeGen/RISCV/GlobalISel/constbarrier-rv32.ll new file mode 100644 index 000000000000..70d1b25309c8 --- /dev/null +++ b/llvm/test/CodeGen/RISCV/GlobalISel/constbarrier-rv32.ll @@ -0,0 +1,60 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 5 +; RUN: llc -mtriple=riscv32 -global-isel -verify-machineinstrs < %s \ +; RUN: | FileCheck %s --check-prefixes=RV32 + +define i16 @constant_fold_barrier_i16(i16 %x, i16 %y) { +; RV32-LABEL: constant_fold_barrier_i16: +; RV32: # %bb.0: # %entry +; RV32-NEXT: li a1, 1 +; RV32-NEXT: slli a1, a1, 11 +; RV32-NEXT: and a0, a0, a1 +; RV32-NEXT: addi a1, a1, 289 +; RV32-NEXT: or a0, a0, a1 +; RV32-NEXT: ret +entry: + %and = and i16 %x, 2048 + %or = or i16 %and, 2337 + ret i16 %or +} + +define void @constant_fold_barrier_i128(ptr %p) { +; RV32-LABEL: constant_fold_barrier_i128: +; RV32: # %bb.0: # %entry +; RV32-NEXT: li a1, 1 +; RV32-NEXT: slli a1, a1, 11 +; RV32-NEXT: lw a2, 0(a0) +; RV32-NEXT: lw a3, 4(a0) +; RV32-NEXT: lw a4, 8(a0) +; RV32-NEXT: lw a5, 12(a0) +; RV32-NEXT: and a2, a2, a1 +; RV32-NEXT: and a3, a3, zero +; RV32-NEXT: and a4, a4, zero +; RV32-NEXT: and a5, a5, zero +; RV32-NEXT: add a2, a2, a1 +; RV32-NEXT: sltu a1, a2, a1 +; RV32-NEXT: add a6, a3, zero +; RV32-NEXT: sltu a3, a6, a3 +; RV32-NEXT: add a6, a6, a1 +; RV32-NEXT: seqz a7, a6 +; RV32-NEXT: and a1, a7, a1 +; RV32-NEXT: or a1, a3, a1 +; RV32-NEXT: add a3, a4, zero +; RV32-NEXT: sltu a4, a3, a4 +; RV32-NEXT: add a3, a3, a1 +; RV32-NEXT: seqz a7, a3 +; RV32-NEXT: and a1, a7, a1 +; RV32-NEXT: or a1, a4, a1 +; RV32-NEXT: add a5, a5, zero +; RV32-NEXT: add a1, a5, a1 +; RV32-NEXT: sw a2, 0(a0) +; RV32-NEXT: sw a6, 4(a0) +; RV32-NEXT: sw a3, 8(a0) +; RV32-NEXT: sw a1, 12(a0) +; RV32-NEXT: ret +entry: + %x = load i128, ptr %p + %and = and i128 %x, 2048 + %add = add i128 %and, 2048 + store i128 %add, ptr %p + ret void +} diff --git a/llvm/test/CodeGen/RISCV/GlobalISel/constbarrier-rv64.ll b/llvm/test/CodeGen/RISCV/GlobalISel/constbarrier-rv64.ll new file mode 100644 index 000000000000..21d7b1d70714 --- /dev/null +++ b/llvm/test/CodeGen/RISCV/GlobalISel/constbarrier-rv64.ll @@ -0,0 +1,36 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 5 +; RUN: llc -mtriple=riscv64 -global-isel -verify-machineinstrs < %s \ +; RUN: | FileCheck %s --check-prefixes=RV64 + +define i16 @constant_fold_barrier_i16(i16 %x, i16 %y) { +; RV64-LABEL: constant_fold_barrier_i16: +; RV64: # %bb.0: # %entry +; RV64-NEXT: li a1, 1 +; RV64-NEXT: slli a1, a1, 11 +; RV64-NEXT: and a0, a0, a1 +; RV64-NEXT: addiw a1, a1, 289 +; RV64-NEXT: or a0, a0, a1 +; RV64-NEXT: ret +entry: + %and = and i16 %x, 2048 + %or = or i16 %and, 2337 + ret i16 %or +} + +define i128 @constant_fold_barrier_i128(i128 %x) { +; RV64-LABEL: constant_fold_barrier_i128: +; RV64: # %bb.0: # %entry +; RV64-NEXT: li a2, 1 +; RV64-NEXT: slli a2, a2, 11 +; RV64-NEXT: and a0, a0, a2 +; RV64-NEXT: and a1, a1, zero +; RV64-NEXT: add a0, a0, a2 +; RV64-NEXT: sltu a2, a0, a2 +; RV64-NEXT: add a1, a1, zero +; RV64-NEXT: add a1, a1, a2 +; RV64-NEXT: ret +entry: + %and = and i128 %x, 2048 + %add = add i128 %and, 2048 + ret i128 %add +} diff --git a/llvm/test/CodeGen/RISCV/GlobalISel/legalizer/legalize-constbarrier-rv32.mir b/llvm/test/CodeGen/RISCV/GlobalISel/legalizer/legalize-constbarrier-rv32.mir index 6b1fc2042e2b..bbe8ef4b092d 100644 --- a/llvm/test/CodeGen/RISCV/GlobalISel/legalizer/legalize-constbarrier-rv32.mir +++ b/llvm/test/CodeGen/RISCV/GlobalISel/legalizer/legalize-constbarrier-rv32.mir @@ -14,6 +14,38 @@ body: | $x10 = COPY %2(s32) PseudoRET implicit $x10 +... +--- +name: constbarrier_i16 +body: | + bb.0.entry: + ; CHECK-LABEL: name: constbarrier_i16 + ; CHECK: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 2048 + ; CHECK-NEXT: [[CONSTANT_FOLD_BARRIER:%[0-9]+]]:_(s32) = G_CONSTANT_FOLD_BARRIER [[C]] + ; CHECK-NEXT: $x10 = COPY [[CONSTANT_FOLD_BARRIER]](s32) + ; CHECK-NEXT: PseudoRET implicit $x10 + %1:_(s16) = G_CONSTANT i16 2048 + %2:_(s16) = G_CONSTANT_FOLD_BARRIER %1 + %3:_(s32) = G_ANYEXT %2(s16) + $x10 = COPY %3(s32) + PseudoRET implicit $x10 + +... +--- +name: constbarrier_i128 +body: | + bb.0.entry: + ; CHECK-LABEL: name: constbarrier_i128 + ; CHECK: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 2048 + ; CHECK-NEXT: [[CONSTANT_FOLD_BARRIER:%[0-9]+]]:_(s32) = G_CONSTANT_FOLD_BARRIER [[C]] + ; CHECK-NEXT: $x10 = COPY [[CONSTANT_FOLD_BARRIER]](s32) + ; CHECK-NEXT: PseudoRET implicit $x10 + %1:_(s128) = G_CONSTANT i128 2048 + %2:_(s128) = G_CONSTANT_FOLD_BARRIER %1 + %3:_(s32) = G_TRUNC %2(s128) + $x10 = COPY %3(s32) + PseudoRET implicit $x10 + ... --- name: constbarrier_nxv2i1 diff --git a/llvm/test/CodeGen/RISCV/GlobalISel/legalizer/legalize-constbarrier-rv64.mir b/llvm/test/CodeGen/RISCV/GlobalISel/legalizer/legalize-constbarrier-rv64.mir index de6a82beee2a..96b1aa53d46e 100644 --- a/llvm/test/CodeGen/RISCV/GlobalISel/legalizer/legalize-constbarrier-rv64.mir +++ b/llvm/test/CodeGen/RISCV/GlobalISel/legalizer/legalize-constbarrier-rv64.mir @@ -31,6 +31,39 @@ body: | $x10 = COPY %2(s64) PseudoRET implicit $x10 +... +--- +name: constbarrier_i16 +body: | + bb.0.entry: + ; CHECK-LABEL: name: constbarrier_i16 + ; CHECK: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 2048 + ; CHECK-NEXT: [[CONSTANT_FOLD_BARRIER:%[0-9]+]]:_(s32) = G_CONSTANT_FOLD_BARRIER [[C]] + ; CHECK-NEXT: [[ANYEXT:%[0-9]+]]:_(s64) = G_ANYEXT [[CONSTANT_FOLD_BARRIER]](s32) + ; CHECK-NEXT: $x10 = COPY [[ANYEXT]](s64) + ; CHECK-NEXT: PseudoRET implicit $x10 + %1:_(s16) = G_CONSTANT i16 2048 + %2:_(s16) = G_CONSTANT_FOLD_BARRIER %1 + %3:_(s64) = G_ANYEXT %2(s16) + $x10 = COPY %3(s64) + PseudoRET implicit $x10 + +... +--- +name: constbarrier_i128 +body: | + bb.0.entry: + ; CHECK-LABEL: name: constbarrier_i128 + ; CHECK: [[C:%[0-9]+]]:_(s64) = G_CONSTANT i64 2048 + ; CHECK-NEXT: [[CONSTANT_FOLD_BARRIER:%[0-9]+]]:_(s64) = G_CONSTANT_FOLD_BARRIER [[C]] + ; CHECK-NEXT: $x10 = COPY [[CONSTANT_FOLD_BARRIER]](s64) + ; CHECK-NEXT: PseudoRET implicit $x10 + %1:_(s128) = G_CONSTANT i128 2048 + %2:_(s128) = G_CONSTANT_FOLD_BARRIER %1 + %3:_(s64) = G_TRUNC %2(s128) + $x10 = COPY %3(s64) + PseudoRET implicit $x10 + ... --- name: constbarrier_nxv2i1 -- GitLab From c0de13b05f9905dbbc582d234214081dd410db1d Mon Sep 17 00:00:00 2001 From: Yingwei Zheng Date: Wed, 22 May 2024 23:36:34 +0800 Subject: [PATCH 142/452] [GISel][RISCV] Legalize shifts with non-trivial shamt types (#93019) This patch widens the illegal shamt type `i48` -> `i64` to fix legalization failure: https://godbolt.org/z/4zMTnoW7h --- .../Target/RISCV/GISel/RISCVLegalizerInfo.cpp | 3 +- .../legalizer/legalize-lshr-rv64.mir | 26 ++++++++++ llvm/test/CodeGen/RISCV/GlobalISel/shift.ll | 48 +++++++++++++++++++ 3 files changed, 76 insertions(+), 1 deletion(-) create mode 100644 llvm/test/CodeGen/RISCV/GlobalISel/shift.ll diff --git a/llvm/lib/Target/RISCV/GISel/RISCVLegalizerInfo.cpp b/llvm/lib/Target/RISCV/GISel/RISCVLegalizerInfo.cpp index e3d74cef7e7f..a1d3aadb816a 100644 --- a/llvm/lib/Target/RISCV/GISel/RISCVLegalizerInfo.cpp +++ b/llvm/lib/Target/RISCV/GISel/RISCVLegalizerInfo.cpp @@ -141,7 +141,8 @@ RISCVLegalizerInfo::RISCVLegalizerInfo(const RISCVSubtarget &ST) .widenScalarToNextPow2(0) .clampScalar(1, s32, sXLen) .clampScalar(0, s32, sXLen) - .minScalarSameAs(1, 0); + .minScalarSameAs(1, 0) + .widenScalarToNextPow2(1); auto &ExtActions = getActionDefinitionsBuilder({G_ZEXT, G_SEXT, G_ANYEXT}) diff --git a/llvm/test/CodeGen/RISCV/GlobalISel/legalizer/legalize-lshr-rv64.mir b/llvm/test/CodeGen/RISCV/GlobalISel/legalizer/legalize-lshr-rv64.mir index 8cbae0fa0173..43318118f09c 100644 --- a/llvm/test/CodeGen/RISCV/GlobalISel/legalizer/legalize-lshr-rv64.mir +++ b/llvm/test/CodeGen/RISCV/GlobalISel/legalizer/legalize-lshr-rv64.mir @@ -336,3 +336,29 @@ body: | PseudoRET implicit $x10 ... +--- +name: lshr_i32_i48 +body: | + bb.1: + liveins: $x10 + + ; CHECK-LABEL: name: lshr_i32_i48 + ; CHECK: liveins: $x10 + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: [[COPY:%[0-9]+]]:_(s64) = COPY $x10 + ; CHECK-NEXT: [[C:%[0-9]+]]:_(s64) = G_CONSTANT i64 16 + ; CHECK-NEXT: [[TRUNC:%[0-9]+]]:_(s32) = G_TRUNC [[COPY]](s64) + ; CHECK-NEXT: [[LSHR:%[0-9]+]]:_(s32) = G_LSHR [[TRUNC]], [[C]](s64) + ; CHECK-NEXT: [[ANYEXT:%[0-9]+]]:_(s64) = G_ANYEXT [[LSHR]](s32) + ; CHECK-NEXT: $x10 = COPY [[ANYEXT]](s64) + ; CHECK-NEXT: PseudoRET implicit $x10 + %1:_(s64) = COPY $x10 + %0:_(s48) = G_TRUNC %1(s64) + %2:_(s48) = G_CONSTANT i48 16 + %6:_(s32) = G_TRUNC %0(s48) + %7:_(s32) = G_LSHR %6, %2(s48) + %5:_(s64) = G_ANYEXT %7(s32) + $x10 = COPY %5(s64) + PseudoRET implicit $x10 + +... diff --git a/llvm/test/CodeGen/RISCV/GlobalISel/shift.ll b/llvm/test/CodeGen/RISCV/GlobalISel/shift.ll new file mode 100644 index 000000000000..b75cbf8e871a --- /dev/null +++ b/llvm/test/CodeGen/RISCV/GlobalISel/shift.ll @@ -0,0 +1,48 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 5 +; RUN: llc -mtriple=riscv32 -global-isel -global-isel-abort=1 -verify-machineinstrs < %s 2>&1 | FileCheck %s --check-prefixes=RV32 +; RUN: llc -mtriple=riscv64 -global-isel -global-isel-abort=1 -verify-machineinstrs < %s 2>&1 | FileCheck %s --check-prefixes=RV64 + +define i16 @test_lshr_i48(i48 %x) { +; RV32-LABEL: test_lshr_i48: +; RV32: # %bb.0: +; RV32-NEXT: srli a0, a0, 16 +; RV32-NEXT: ret +; +; RV64-LABEL: test_lshr_i48: +; RV64: # %bb.0: +; RV64-NEXT: srliw a0, a0, 16 +; RV64-NEXT: ret + %lshr = lshr i48 %x, 16 + %trunc = trunc i48 %lshr to i16 + ret i16 %trunc +} + +define i16 @test_ashr_i48(i48 %x) { +; RV32-LABEL: test_ashr_i48: +; RV32: # %bb.0: +; RV32-NEXT: srai a0, a0, 16 +; RV32-NEXT: ret +; +; RV64-LABEL: test_ashr_i48: +; RV64: # %bb.0: +; RV64-NEXT: sraiw a0, a0, 16 +; RV64-NEXT: ret + %ashr = ashr i48 %x, 16 + %trunc = trunc i48 %ashr to i16 + ret i16 %trunc +} + +define i16 @test_shl_i48(i48 %x) { +; RV32-LABEL: test_shl_i48: +; RV32: # %bb.0: +; RV32-NEXT: slli a0, a0, 8 +; RV32-NEXT: ret +; +; RV64-LABEL: test_shl_i48: +; RV64: # %bb.0: +; RV64-NEXT: slliw a0, a0, 8 +; RV64-NEXT: ret + %shl = shl i48 %x, 8 + %trunc = trunc i48 %shl to i16 + ret i16 %trunc +} -- GitLab From 919df9d75ac2a721a8072327c803f34486884571 Mon Sep 17 00:00:00 2001 From: Balazs Benics Date: Wed, 22 May 2024 17:41:31 +0200 Subject: [PATCH 143/452] [clang][AST] Fix end location of DeclarationNameInfo on instantiated methods (#92654) Fixes #71161 [D64087](https://reviews.llvm.org/D64087) updated some locations of the instantiated method but forgot `DNLoc`. `FunctionDecl::getNameInfo()` constructs a `DeclarationNameInfo` using `Decl::Loc` as the beginning of the declaration name, and `FunctionDecl::DNLoc` to compute the end of the declaration name. The former was updated, but the latter was not, so `DeclarationName::getSourceRange()` would return a range where the end of the declaration name could come before its beginning. Patch by Alejandro Alvarez Ayllon Co-authored-by: steakhal CPP-5166 Co-authored-by: Alejandro Alvarez Ayllon --- clang/docs/ReleaseNotes.rst | 1 + clang/include/clang/AST/Decl.h | 2 ++ .../lib/Sema/SemaTemplateInstantiateDecl.cpp | 1 + clang/unittests/AST/DeclTest.cpp | 31 +++++++++++++++++++ 4 files changed, 35 insertions(+) diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 2899bc5ed35a..93b6ba59ecf9 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -766,6 +766,7 @@ Miscellaneous Bug Fixes - Fixed an infinite recursion in ASTImporter, on return type declared inside body of C++11 lambda without trailing return (#GH68775). +- Fixed declaration name source location of instantiated function definitions (GH71161). Miscellaneous Clang Crashes Fixed ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/clang/include/clang/AST/Decl.h b/clang/include/clang/AST/Decl.h index 5e485ccb85a1..7fd80b90d103 100644 --- a/clang/include/clang/AST/Decl.h +++ b/clang/include/clang/AST/Decl.h @@ -2188,6 +2188,8 @@ public: void setRangeEnd(SourceLocation E) { EndRangeLoc = E; } + void setDeclarationNameLoc(DeclarationNameLoc L) { DNLoc = L; } + /// Returns the location of the ellipsis of a variadic function. SourceLocation getEllipsisLoc() const { const auto *FPT = getType()->getAs(); diff --git a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp index 09812946bd38..bb49aae2cb66 100644 --- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -5055,6 +5055,7 @@ void Sema::InstantiateFunctionDefinition(SourceLocation PointOfInstantiation, Function->setLocation(PatternDecl->getLocation()); Function->setInnerLocStart(PatternDecl->getInnerLocStart()); Function->setRangeEnd(PatternDecl->getEndLoc()); + Function->setDeclarationNameLoc(PatternDecl->getNameInfo().getInfo()); EnterExpressionEvaluationContext EvalContext( *this, Sema::ExpressionEvaluationContext::PotentiallyEvaluated); diff --git a/clang/unittests/AST/DeclTest.cpp b/clang/unittests/AST/DeclTest.cpp index 2530ce74eb6a..16aa2b50b7a0 100644 --- a/clang/unittests/AST/DeclTest.cpp +++ b/clang/unittests/AST/DeclTest.cpp @@ -545,3 +545,34 @@ TEST(Decl, TemplateArgumentDefaulted) { EXPECT_TRUE(ArgList.get(2).getIsDefaulted()); EXPECT_TRUE(ArgList.get(3).getIsDefaulted()); } + +TEST(Decl, CXXDestructorDeclsShouldHaveWellFormedNameInfoRanges) { + // GH71161 + llvm::Annotations Code(R"cpp( +template struct Resource { + ~Resource(); // 1 +}; +template +Resource::~Resource() {} // 2,3 + +void instantiate_template() { + Resource x; +} +)cpp"); + + auto AST = tooling::buildASTFromCode(Code.code()); + ASTContext &Ctx = AST->getASTContext(); + + const auto &SM = Ctx.getSourceManager(); + auto GetNameInfoRange = [&SM](const BoundNodes &Match) { + const auto *D = Match.getNodeAs("dtor"); + return D->getNameInfo().getSourceRange().printToString(SM); + }; + + auto Matches = match(findAll(cxxDestructorDecl().bind("dtor")), + *Ctx.getTranslationUnitDecl(), Ctx); + ASSERT_EQ(Matches.size(), 3U); + EXPECT_EQ(GetNameInfoRange(Matches[0]), ""); + EXPECT_EQ(GetNameInfoRange(Matches[1]), ""); + EXPECT_EQ(GetNameInfoRange(Matches[2]), ""); +} -- GitLab From eeb9fcddf5f29ce967442437f15dea174bb04345 Mon Sep 17 00:00:00 2001 From: Tom Eccles Date: Wed, 22 May 2024 16:48:50 +0100 Subject: [PATCH 144/452] [flang][HLFIR][NFC] Use tablegen to reduce assignment pass boilerplate (#93030) This pass is module-level and then runs on all operations implementing the ordered assignment interface. It should not matter which top-level operation the assignment is inside of. This commit removes some unnecessary boilerplate that we can generate automatically with tablegen. --- flang/include/flang/Optimizer/HLFIR/Passes.h | 1 - flang/include/flang/Optimizer/HLFIR/Passes.td | 1 - flang/include/flang/Tools/CLOptions.inc | 2 +- .../HLFIR/Transforms/LowerHLFIROrderedAssignments.cpp | 7 +++---- 4 files changed, 4 insertions(+), 7 deletions(-) diff --git a/flang/include/flang/Optimizer/HLFIR/Passes.h b/flang/include/flang/Optimizer/HLFIR/Passes.h index 5035415ede2d..e0b4111eed6b 100644 --- a/flang/include/flang/Optimizer/HLFIR/Passes.h +++ b/flang/include/flang/Optimizer/HLFIR/Passes.h @@ -25,7 +25,6 @@ namespace hlfir { std::unique_ptr createConvertHLFIRtoFIRPass(); std::unique_ptr createBufferizeHLFIRPass(); std::unique_ptr createLowerHLFIRIntrinsicsPass(); -std::unique_ptr createLowerHLFIROrderedAssignmentsPass(); #define GEN_PASS_REGISTRATION #include "flang/Optimizer/HLFIR/Passes.h.inc" diff --git a/flang/include/flang/Optimizer/HLFIR/Passes.td b/flang/include/flang/Optimizer/HLFIR/Passes.td index 0fe2d9c0a632..9555467a57ad 100644 --- a/flang/include/flang/Optimizer/HLFIR/Passes.td +++ b/flang/include/flang/Optimizer/HLFIR/Passes.td @@ -34,7 +34,6 @@ def LowerHLFIRIntrinsics : Pass<"lower-hlfir-intrinsics", "::mlir::ModuleOp"> { def LowerHLFIROrderedAssignments : Pass<"lower-hlfir-ordered-assignments", "::mlir::ModuleOp"> { let summary = "Lower HLFIR ordered assignments like forall and where operations"; - let constructor = "hlfir::createLowerHLFIROrderedAssignmentsPass()"; let options = [ Option<"tryFusingAssignments", "fuse-assignments", "bool", /*default=*/"false", diff --git a/flang/include/flang/Tools/CLOptions.inc b/flang/include/flang/Tools/CLOptions.inc index 82a8aece8275..69934281fa99 100644 --- a/flang/include/flang/Tools/CLOptions.inc +++ b/flang/include/flang/Tools/CLOptions.inc @@ -327,7 +327,7 @@ inline void createHLFIRToFIRPassPipeline( addNestedPassToAllTopLevelOperations( pm, hlfir::createOptimizedBufferization); } - pm.addPass(hlfir::createLowerHLFIROrderedAssignmentsPass()); + pm.addPass(hlfir::createLowerHLFIROrderedAssignments()); pm.addPass(hlfir::createLowerHLFIRIntrinsicsPass()); pm.addPass(hlfir::createBufferizeHLFIRPass()); pm.addPass(hlfir::createConvertHLFIRtoFIRPass()); diff --git a/flang/lib/Optimizer/HLFIR/Transforms/LowerHLFIROrderedAssignments.cpp b/flang/lib/Optimizer/HLFIR/Transforms/LowerHLFIROrderedAssignments.cpp index c9ff4b1c3374..a1a89bb5154f 100644 --- a/flang/lib/Optimizer/HLFIR/Transforms/LowerHLFIROrderedAssignments.cpp +++ b/flang/lib/Optimizer/HLFIR/Transforms/LowerHLFIROrderedAssignments.cpp @@ -1383,6 +1383,9 @@ class LowerHLFIROrderedAssignments : public hlfir::impl::LowerHLFIROrderedAssignmentsBase< LowerHLFIROrderedAssignments> { public: + using LowerHLFIROrderedAssignmentsBase< + LowerHLFIROrderedAssignments>::LowerHLFIROrderedAssignmentsBase; + void runOnOperation() override { // Running on a ModuleOp because this pass may generate FuncOp declaration // for runtime calls. This could be a FuncOp pass otherwise. @@ -1409,7 +1412,3 @@ public: } }; } // namespace - -std::unique_ptr hlfir::createLowerHLFIROrderedAssignmentsPass() { - return std::make_unique(); -} -- GitLab From 101f977f2c218f4a27f3a04b3b324b61c80570d6 Mon Sep 17 00:00:00 2001 From: Krzysztof Parzyszek Date: Wed, 22 May 2024 10:52:17 -0500 Subject: [PATCH 145/452] [flang][CodeGen] Avoid out-of-bounds memory access in SelectCaseOp (#92955) `SelectCaseOp::getCompareOperands` may return an empty range for the "default" case. Do not dereference the range until it is expected to be non-empty. This was detected by address-sanitizer. --- flang/lib/Optimizer/CodeGen/CodeGen.cpp | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/flang/lib/Optimizer/CodeGen/CodeGen.cpp b/flang/lib/Optimizer/CodeGen/CodeGen.cpp index fb7afcf07713..74e68725003c 100644 --- a/flang/lib/Optimizer/CodeGen/CodeGen.cpp +++ b/flang/lib/Optimizer/CodeGen/CodeGen.cpp @@ -2981,39 +2981,40 @@ struct SelectCaseOpConversion : public fir::FIROpConversion { caseOp.getSuccessorOperands(adaptor.getOperands(), t); std::optional cmpOps = *caseOp.getCompareOperands(adaptor.getOperands(), t); - mlir::Value caseArg = *(cmpOps.value().begin()); mlir::Attribute attr = cases[t]; + assert(mlir::isa(attr) || cmpOps.has_value()); if (mlir::isa(attr)) { auto cmp = rewriter.create( - loc, mlir::LLVM::ICmpPredicate::eq, selector, caseArg); + loc, mlir::LLVM::ICmpPredicate::eq, selector, cmpOps->front()); genCaseLadderStep(loc, cmp, dest, destOps, rewriter); continue; } if (mlir::isa(attr)) { auto cmp = rewriter.create( - loc, mlir::LLVM::ICmpPredicate::sle, caseArg, selector); + loc, mlir::LLVM::ICmpPredicate::sle, cmpOps->front(), selector); genCaseLadderStep(loc, cmp, dest, destOps, rewriter); continue; } if (mlir::isa(attr)) { auto cmp = rewriter.create( - loc, mlir::LLVM::ICmpPredicate::sle, selector, caseArg); + loc, mlir::LLVM::ICmpPredicate::sle, selector, cmpOps->front()); genCaseLadderStep(loc, cmp, dest, destOps, rewriter); continue; } if (mlir::isa(attr)) { - auto cmp = rewriter.create( - loc, mlir::LLVM::ICmpPredicate::sle, caseArg, selector); + mlir::Value caseArg0 = *cmpOps->begin(); + auto cmp0 = rewriter.create( + loc, mlir::LLVM::ICmpPredicate::sle, caseArg0, selector); auto *thisBlock = rewriter.getInsertionBlock(); auto *newBlock1 = createBlock(rewriter, dest); auto *newBlock2 = createBlock(rewriter, dest); rewriter.setInsertionPointToEnd(thisBlock); - rewriter.create(loc, cmp, newBlock1, newBlock2); + rewriter.create(loc, cmp0, newBlock1, newBlock2); rewriter.setInsertionPointToEnd(newBlock1); - mlir::Value caseArg0 = *(cmpOps.value().begin() + 1); - auto cmp0 = rewriter.create( - loc, mlir::LLVM::ICmpPredicate::sle, selector, caseArg0); - genCondBrOp(loc, cmp0, dest, destOps, rewriter, newBlock2); + mlir::Value caseArg1 = *(cmpOps->begin() + 1); + auto cmp1 = rewriter.create( + loc, mlir::LLVM::ICmpPredicate::sle, selector, caseArg1); + genCondBrOp(loc, cmp1, dest, destOps, rewriter, newBlock2); rewriter.setInsertionPointToEnd(newBlock2); continue; } -- GitLab From ac1dc05b331d35f341631f798673fe8aafdda53d Mon Sep 17 00:00:00 2001 From: Adrian Prantl Date: Wed, 22 May 2024 08:52:33 -0700 Subject: [PATCH 146/452] Change GetChildCompilerTypeAtIndex to return Expected (NFC) (#92979) This change is a general improvement of the internal API. My motivation is to use this in the Swift typesystem plugin. --- lldb/include/lldb/Symbol/CompilerType.h | 2 +- lldb/include/lldb/Symbol/TypeSystem.h | 2 +- lldb/source/Core/ValueObject.cpp | 31 ++++++++++++++----- .../Core/ValueObjectConstResultImpl.cpp | 12 +++++-- .../Plugins/ABI/PowerPC/ABISysV_ppc64.cpp | 3 +- .../Language/CPlusPlus/BlockPointer.cpp | 18 ++++++----- .../Plugins/Language/CPlusPlus/LibCxxMap.cpp | 14 ++++----- .../TypeSystem/Clang/TypeSystemClang.cpp | 18 ++++++----- .../TypeSystem/Clang/TypeSystemClang.h | 2 +- lldb/source/Symbol/CompilerType.cpp | 2 +- 10 files changed, 67 insertions(+), 37 deletions(-) diff --git a/lldb/include/lldb/Symbol/CompilerType.h b/lldb/include/lldb/Symbol/CompilerType.h index 28c723abf279..70dacdcb7986 100644 --- a/lldb/include/lldb/Symbol/CompilerType.h +++ b/lldb/include/lldb/Symbol/CompilerType.h @@ -436,7 +436,7 @@ public: uint32_t *bitfield_bit_size_ptr = nullptr, bool *is_bitfield_ptr = nullptr) const; - CompilerType GetChildCompilerTypeAtIndex( + llvm::Expected GetChildCompilerTypeAtIndex( ExecutionContext *exe_ctx, size_t idx, bool transparent_pointers, bool omit_empty_base_classes, bool ignore_array_bounds, std::string &child_name, uint32_t &child_byte_size, diff --git a/lldb/include/lldb/Symbol/TypeSystem.h b/lldb/include/lldb/Symbol/TypeSystem.h index 7bcb8d69387a..b4025c173a18 100644 --- a/lldb/include/lldb/Symbol/TypeSystem.h +++ b/lldb/include/lldb/Symbol/TypeSystem.h @@ -359,7 +359,7 @@ public: return CompilerDecl(); } - virtual CompilerType GetChildCompilerTypeAtIndex( + virtual llvm::Expected GetChildCompilerTypeAtIndex( lldb::opaque_compiler_type_t type, ExecutionContext *exe_ctx, size_t idx, bool transparent_pointers, bool omit_empty_base_classes, bool ignore_array_bounds, std::string &child_name, diff --git a/lldb/source/Core/ValueObject.cpp b/lldb/source/Core/ValueObject.cpp index f39bd07a2553..1443d9dfc328 100644 --- a/lldb/source/Core/ValueObject.cpp +++ b/lldb/source/Core/ValueObject.cpp @@ -505,15 +505,23 @@ ValueObject *ValueObject::CreateChildAtIndex(size_t idx, uint64_t language_flags = 0; const bool transparent_pointers = !synthetic_array_member; - CompilerType child_compiler_type; ExecutionContext exe_ctx(GetExecutionContextRef()); - child_compiler_type = GetCompilerType().GetChildCompilerTypeAtIndex( - &exe_ctx, idx, transparent_pointers, omit_empty_base_classes, - ignore_array_bounds, child_name_str, child_byte_size, child_byte_offset, - child_bitfield_bit_size, child_bitfield_bit_offset, child_is_base_class, - child_is_deref_of_parent, this, language_flags); + auto child_compiler_type_or_err = + GetCompilerType().GetChildCompilerTypeAtIndex( + &exe_ctx, idx, transparent_pointers, omit_empty_base_classes, + ignore_array_bounds, child_name_str, child_byte_size, + child_byte_offset, child_bitfield_bit_size, child_bitfield_bit_offset, + child_is_base_class, child_is_deref_of_parent, this, language_flags); + CompilerType child_compiler_type; + if (!child_compiler_type_or_err) + LLDB_LOG_ERROR(GetLog(LLDBLog::Types), + child_compiler_type_or_err.takeError(), + "could not find child: {0}"); + else + child_compiler_type = *child_compiler_type_or_err; + if (child_compiler_type) { if (synthetic_index) child_byte_offset += child_byte_size * synthetic_index; @@ -2624,16 +2632,23 @@ ValueObjectSP ValueObject::Dereference(Status &error) { bool child_is_deref_of_parent = false; const bool transparent_pointers = false; CompilerType compiler_type = GetCompilerType(); - CompilerType child_compiler_type; uint64_t language_flags = 0; ExecutionContext exe_ctx(GetExecutionContextRef()); - child_compiler_type = compiler_type.GetChildCompilerTypeAtIndex( + CompilerType child_compiler_type; + auto child_compiler_type_or_err = compiler_type.GetChildCompilerTypeAtIndex( &exe_ctx, 0, transparent_pointers, omit_empty_base_classes, ignore_array_bounds, child_name_str, child_byte_size, child_byte_offset, child_bitfield_bit_size, child_bitfield_bit_offset, child_is_base_class, child_is_deref_of_parent, this, language_flags); + if (!child_compiler_type_or_err) + LLDB_LOG_ERROR(GetLog(LLDBLog::Types), + child_compiler_type_or_err.takeError(), + "could not find child: {0}"); + else + child_compiler_type = *child_compiler_type_or_err; + if (child_compiler_type && child_byte_size) { ConstString child_name; if (!child_name_str.empty()) diff --git a/lldb/source/Core/ValueObjectConstResultImpl.cpp b/lldb/source/Core/ValueObjectConstResultImpl.cpp index e2db3ace1924..493980d7ea96 100644 --- a/lldb/source/Core/ValueObjectConstResultImpl.cpp +++ b/lldb/source/Core/ValueObjectConstResultImpl.cpp @@ -17,6 +17,8 @@ #include "lldb/Target/ExecutionContext.h" #include "lldb/Utility/DataBufferHeap.h" #include "lldb/Utility/Endian.h" +#include "lldb/Utility/LLDBLog.h" +#include "lldb/Utility/Log.h" #include "lldb/Utility/Scalar.h" #include @@ -66,15 +68,21 @@ ValueObject *ValueObjectConstResultImpl::CreateChildAtIndex( const bool transparent_pointers = !synthetic_array_member; CompilerType compiler_type = m_impl_backend->GetCompilerType(); - CompilerType child_compiler_type; ExecutionContext exe_ctx(m_impl_backend->GetExecutionContextRef()); - child_compiler_type = compiler_type.GetChildCompilerTypeAtIndex( + auto child_compiler_type_or_err = compiler_type.GetChildCompilerTypeAtIndex( &exe_ctx, idx, transparent_pointers, omit_empty_base_classes, ignore_array_bounds, child_name_str, child_byte_size, child_byte_offset, child_bitfield_bit_size, child_bitfield_bit_offset, child_is_base_class, child_is_deref_of_parent, m_impl_backend, language_flags); + CompilerType child_compiler_type; + if (!child_compiler_type_or_err) + LLDB_LOG_ERROR(GetLog(LLDBLog::Types), + child_compiler_type_or_err.takeError(), + "could not find child: {0}"); + else + child_compiler_type = *child_compiler_type_or_err; // One might think we should check that the size of the children // is always strictly positive, hence we could avoid creating a diff --git a/lldb/source/Plugins/ABI/PowerPC/ABISysV_ppc64.cpp b/lldb/source/Plugins/ABI/PowerPC/ABISysV_ppc64.cpp index 173b5613d1b8..3d9b4566ca1c 100644 --- a/lldb/source/Plugins/ABI/PowerPC/ABISysV_ppc64.cpp +++ b/lldb/source/Plugins/ABI/PowerPC/ABISysV_ppc64.cpp @@ -903,7 +903,8 @@ private: } // get child - CompilerType GetChildType(uint32_t i, std::string &name, uint32_t &size) { + llvm::Expected GetChildType(uint32_t i, std::string &name, + uint32_t &size) { // GetChild constant inputs const bool transparent_pointers = false; const bool omit_empty_base_classes = true; diff --git a/lldb/source/Plugins/Language/CPlusPlus/BlockPointer.cpp b/lldb/source/Plugins/Language/CPlusPlus/BlockPointer.cpp index 9a6e135e0083..2c9b3c425397 100644 --- a/lldb/source/Plugins/Language/CPlusPlus/BlockPointer.cpp +++ b/lldb/source/Plugins/Language/CPlusPlus/BlockPointer.cpp @@ -12,6 +12,7 @@ #include "Plugins/ExpressionParser/Clang/ClangPersistentVariables.h" #include "Plugins/TypeSystem/Clang/TypeSystemClang.h" #include "lldb/Core/ValueObject.h" +#include "lldb/Core/ValueObjectConstResult.h" #include "lldb/DataFormatters/FormattersHelpers.h" #include "lldb/Symbol/CompilerType.h" #include "lldb/Symbol/TypeSystem.h" @@ -105,13 +106,16 @@ public: bool child_is_deref_of_parent = false; uint64_t language_flags = 0; - const CompilerType child_type = - m_block_struct_type.GetChildCompilerTypeAtIndex( - &exe_ctx, idx, transparent_pointers, omit_empty_base_classes, - ignore_array_bounds, child_name, child_byte_size, child_byte_offset, - child_bitfield_bit_size, child_bitfield_bit_offset, - child_is_base_class, child_is_deref_of_parent, value_object, - language_flags); + auto child_type_or_err = m_block_struct_type.GetChildCompilerTypeAtIndex( + &exe_ctx, idx, transparent_pointers, omit_empty_base_classes, + ignore_array_bounds, child_name, child_byte_size, child_byte_offset, + child_bitfield_bit_size, child_bitfield_bit_offset, child_is_base_class, + child_is_deref_of_parent, value_object, language_flags); + if (!child_type_or_err) + return ValueObjectConstResult::Create( + exe_ctx.GetBestExecutionContextScope(), + Status(child_type_or_err.takeError())); + CompilerType child_type = *child_type_or_err; ValueObjectSP struct_pointer_sp = m_backend.Cast(m_block_struct_type.GetPointerType()); diff --git a/lldb/source/Plugins/Language/CPlusPlus/LibCxxMap.cpp b/lldb/source/Plugins/Language/CPlusPlus/LibCxxMap.cpp index ec5b320e2218..0929d49e55ea 100644 --- a/lldb/source/Plugins/Language/CPlusPlus/LibCxxMap.cpp +++ b/lldb/source/Plugins/Language/CPlusPlus/LibCxxMap.cpp @@ -295,13 +295,13 @@ void lldb_private::formatters::LibcxxStdMapSyntheticFrontEnd::GetValueOffset( bool child_is_base_class; bool child_is_deref_of_parent; uint64_t language_flags; - if (tree_node_type - .GetChildCompilerTypeAtIndex( - nullptr, 4, true, true, true, child_name, child_byte_size, - child_byte_offset, child_bitfield_bit_size, - child_bitfield_bit_offset, child_is_base_class, - child_is_deref_of_parent, nullptr, language_flags) - .IsValid()) + auto child_type = + llvm::expectedToStdOptional(tree_node_type.GetChildCompilerTypeAtIndex( + nullptr, 4, true, true, true, child_name, child_byte_size, + child_byte_offset, child_bitfield_bit_size, + child_bitfield_bit_offset, child_is_base_class, + child_is_deref_of_parent, nullptr, language_flags)); + if (child_type && child_type->IsValid()) m_skip_size = (uint32_t)child_byte_offset; } } diff --git a/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp b/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp index 582d9eac3e1d..1b2235b4b2b5 100644 --- a/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp +++ b/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp @@ -6130,7 +6130,7 @@ uint32_t TypeSystemClang::GetNumPointeeChildren(clang::QualType type) { return 0; } -CompilerType TypeSystemClang::GetChildCompilerTypeAtIndex( +llvm::Expected TypeSystemClang::GetChildCompilerTypeAtIndex( lldb::opaque_compiler_type_t type, ExecutionContext *exe_ctx, size_t idx, bool transparent_pointers, bool omit_empty_base_classes, bool ignore_array_bounds, std::string &child_name, @@ -6156,11 +6156,8 @@ CompilerType TypeSystemClang::GetChildCompilerTypeAtIndex( auto num_children_or_err = GetNumChildren(type, omit_empty_base_classes, exe_ctx); - if (!num_children_or_err) { - LLDB_LOG_ERRORV(GetLog(LLDBLog::Types), num_children_or_err.takeError(), - "{0}"); - return {}; - } + if (!num_children_or_err) + return num_children_or_err.takeError(); const bool idx_is_valid = idx < *num_children_or_err; int32_t bit_offset; @@ -6242,7 +6239,10 @@ CompilerType TypeSystemClang::GetChildCompilerTypeAtIndex( std::optional size = base_class_clang_type.GetBitSize(get_exe_scope()); if (!size) - return {}; + return llvm::make_error( + "no size info for base class", + llvm::inconvertibleErrorCode()); + uint64_t base_class_clang_type_bit_size = *size; // Base classes bit sizes should be a multiple of 8 bits in size @@ -6274,7 +6274,9 @@ CompilerType TypeSystemClang::GetChildCompilerTypeAtIndex( std::optional size = field_clang_type.GetByteSize(get_exe_scope()); if (!size) - return {}; + return llvm::make_error( + "no size info for field", llvm::inconvertibleErrorCode()); + child_byte_size = *size; const uint32_t child_bit_size = child_byte_size * 8; diff --git a/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.h b/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.h index 042379d40bcb..d67b7a4c9fe7 100644 --- a/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.h +++ b/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.h @@ -887,7 +887,7 @@ public: static uint32_t GetNumPointeeChildren(clang::QualType type); - CompilerType GetChildCompilerTypeAtIndex( + llvm::Expected GetChildCompilerTypeAtIndex( lldb::opaque_compiler_type_t type, ExecutionContext *exe_ctx, size_t idx, bool transparent_pointers, bool omit_empty_base_classes, bool ignore_array_bounds, std::string &child_name, diff --git a/lldb/source/Symbol/CompilerType.cpp b/lldb/source/Symbol/CompilerType.cpp index 072dbccec44f..b5269cf66235 100644 --- a/lldb/source/Symbol/CompilerType.cpp +++ b/lldb/source/Symbol/CompilerType.cpp @@ -902,7 +902,7 @@ uint32_t CompilerType::GetIndexOfFieldWithName( return UINT32_MAX; } -CompilerType CompilerType::GetChildCompilerTypeAtIndex( +llvm::Expected CompilerType::GetChildCompilerTypeAtIndex( ExecutionContext *exe_ctx, size_t idx, bool transparent_pointers, bool omit_empty_base_classes, bool ignore_array_bounds, std::string &child_name, uint32_t &child_byte_size, -- GitLab From 4fbc95d1360147e9c4aceeadd1bda17d68364b85 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timm=20B=C3=A4der?= Date: Wed, 22 May 2024 15:30:51 +0200 Subject: [PATCH 147/452] [clang][Interp] Skip union members in default initializers --- clang/lib/AST/Interp/ByteCodeExprGen.cpp | 4 ++++ clang/lib/AST/Interp/EvaluationResult.cpp | 8 ++++---- clang/test/AST/Interp/unions.cpp | 8 ++++++++ 3 files changed, 16 insertions(+), 4 deletions(-) diff --git a/clang/lib/AST/Interp/ByteCodeExprGen.cpp b/clang/lib/AST/Interp/ByteCodeExprGen.cpp index 859a3fabea32..50c85bf7d35f 100644 --- a/clang/lib/AST/Interp/ByteCodeExprGen.cpp +++ b/clang/lib/AST/Interp/ByteCodeExprGen.cpp @@ -1061,6 +1061,10 @@ bool ByteCodeExprGen::visitInitList(ArrayRef Inits, R->getField(InitIndex)->Decl->isUnnamedBitField()) ++InitIndex; + // Potentially skip ahead. This is especially relevant in unions. + if (const auto *D = dyn_cast(Init)) + InitIndex = D->getField()->getFieldIndex(); + if (!this->emitDupPtr(E)) return false; diff --git a/clang/lib/AST/Interp/EvaluationResult.cpp b/clang/lib/AST/Interp/EvaluationResult.cpp index 79f222ce2b30..150a793da881 100644 --- a/clang/lib/AST/Interp/EvaluationResult.cpp +++ b/clang/lib/AST/Interp/EvaluationResult.cpp @@ -101,6 +101,10 @@ static bool CheckFieldsInitialized(InterpState &S, SourceLocation Loc, Pointer FieldPtr = BasePtr.atField(F.Offset); QualType FieldType = F.Decl->getType(); + // Don't check inactive union members. + if (R->isUnion() && !FieldPtr.isActive()) + continue; + if (FieldType->isRecordType()) { Result &= CheckFieldsInitialized(S, Loc, FieldPtr, FieldPtr.getRecord()); } else if (FieldType->isIncompleteArrayType()) { @@ -115,10 +119,6 @@ static bool CheckFieldsInitialized(InterpState &S, SourceLocation Loc, DiagnoseUninitializedSubobject(S, Loc, F.Decl); Result = false; } - - // Only the first member of a union needs to be initialized. - if (R->isUnion()) - break; } // Check Fields in all bases diff --git a/clang/test/AST/Interp/unions.cpp b/clang/test/AST/Interp/unions.cpp index 004e500de064..46ba514b47b9 100644 --- a/clang/test/AST/Interp/unions.cpp +++ b/clang/test/AST/Interp/unions.cpp @@ -10,3 +10,11 @@ constexpr U a = {12}; static_assert(a.a == 12, ""); static_assert(a.b == 0, ""); // both-error {{not an integral constant expression}} \ // both-note {{read of member 'b' of union with active member 'a'}} +union U1 { + int i; + float f = 3.0f; +}; +constexpr U1 u1{}; +static_assert(u1.f == 3.0, ""); +static_assert(u1.i == 1, ""); // both-error {{not an integral constant expression}} \ + // both-note {{read of member 'i' of union with active member 'f'}} -- GitLab From c44fa3e8a9a44c2e9a575768a3c185354b9f6c17 Mon Sep 17 00:00:00 2001 From: Sirraide Date: Wed, 22 May 2024 17:58:48 +0200 Subject: [PATCH 148/452] [Clang] Refactor `__attribute__((assume))` (#84934) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is a followup to #81014 and #84582: Before this patch, Clang would accept `__attribute__((assume))` and `[[clang::assume]]` as nonstandard spellings for the `[[omp::assume]]` attribute; this resulted in a potentially very confusing name clash with C++23’s `[[assume]]` attribute (and GCC’s `assume` attribute with the same semantics). This pr replaces every usage of `__attribute__((assume))` with `[[omp::assume]]` and makes `__attribute__((assume))` and `[[clang::assume]]` alternative spellings for C++23’s `[[assume]]`; this shouldn’t cause any problems due to differences in appertainment and because almost no-one was using this variant spelling to begin with (a use in libclc has already been changed to use a different attribute). --- clang/include/clang/Basic/Attr.td | 5 +- clang/include/clang/Basic/AttrDocs.td | 7 +- .../clang/Basic/DiagnosticSemaKinds.td | 3 - clang/include/clang/Parse/Parser.h | 3 +- clang/lib/Parse/ParseDecl.cpp | 7 ++ clang/lib/Parse/ParseDeclCXX.cpp | 7 +- clang/lib/Sema/SemaStmtAttr.cpp | 8 +- clang/test/CodeGen/assume_attr.c | 58 -------------- clang/test/CodeGenCXX/assume_attr.cpp | 48 +++++------ clang/test/OpenMP/assumes_codegen.cpp | 80 +++++++++---------- clang/test/OpenMP/assumes_print.cpp | 6 +- clang/test/OpenMP/assumes_template_print.cpp | 20 ++--- ...rallel_in_multiple_target_state_machines.c | 8 +- ...remarks_parallel_in_target_state_machine.c | 4 +- clang/test/Sema/attr-assume.c | 14 ---- clang/test/SemaCXX/cxx23-assume.cpp | 15 ++++ llvm/lib/Transforms/IPO/OpenMPOpt.cpp | 4 +- .../OpenMP/custom_state_machines.ll | 2 +- .../OpenMP/custom_state_machines_pre_lto.ll | 2 +- .../OpenMP/custom_state_machines_remarks.ll | 10 +-- llvm/test/Transforms/OpenMP/spmdization.ll | 4 +- .../Transforms/OpenMP/spmdization_guarding.ll | 4 +- .../Transforms/OpenMP/spmdization_remarks.ll | 14 ++-- openmp/docs/remarks/OMP121.rst | 6 +- openmp/docs/remarks/OMP133.rst | 6 +- openmp/docs/remarks/OptimizationRemarks.rst | 4 +- 26 files changed, 150 insertions(+), 199 deletions(-) delete mode 100644 clang/test/CodeGen/assume_attr.c delete mode 100644 clang/test/Sema/attr-assume.c diff --git a/clang/include/clang/Basic/Attr.td b/clang/include/clang/Basic/Attr.td index 7008bea483c8..a2c8cc42195f 100644 --- a/clang/include/clang/Basic/Attr.td +++ b/clang/include/clang/Basic/Attr.td @@ -1640,10 +1640,11 @@ def Unlikely : StmtAttr { def : MutualExclusions<[Likely, Unlikely]>; def CXXAssume : StmtAttr { - let Spellings = [CXX11<"", "assume", 202207>]; + let Spellings = [CXX11<"", "assume", 202207>, Clang<"assume">]; let Subjects = SubjectList<[NullStmt], ErrorDiag, "empty statements">; let Args = [ExprArgument<"Assumption">]; let Documentation = [CXXAssumeDocs]; + let HasCustomParsing = 1; } def NoMerge : DeclOrStmtAttr { @@ -4255,7 +4256,7 @@ def OMPDeclareVariant : InheritableAttr { } def OMPAssume : InheritableAttr { - let Spellings = [Clang<"assume">, CXX11<"omp", "assume">]; + let Spellings = [CXX11<"omp", "assume">]; let Subjects = SubjectList<[Function, ObjCMethod]>; let InheritEvenIfAlreadyPresent = 1; let Documentation = [OMPAssumeDocs]; diff --git a/clang/include/clang/Basic/AttrDocs.td b/clang/include/clang/Basic/AttrDocs.td index 54197d588eb4..a313e811c9d2 100644 --- a/clang/include/clang/Basic/AttrDocs.td +++ b/clang/include/clang/Basic/AttrDocs.td @@ -2027,9 +2027,6 @@ Different optimisers are likely to react differently to the presence of this attribute; in some cases, adding ``assume`` may affect performance negatively. It should be used with parsimony and care. -Note that `clang::assume` is a different attribute. Always write ``assume`` -without a namespace if you intend to use the standard C++ attribute. - Example: .. code-block:: c++ @@ -4740,7 +4737,7 @@ def OMPAssumeDocs : Documentation { let Category = DocCatFunction; let Heading = "assume"; let Content = [{ -Clang supports the ``__attribute__((assume("assumption")))`` attribute to +Clang supports the ``[[omp::assume("assumption")]]`` attribute to provide additional information to the optimizer. The string-literal, here "assumption", will be attached to the function declaration such that later analysis and optimization passes can assume the "assumption" to hold. @@ -4752,7 +4749,7 @@ A function can have multiple assume attributes and they propagate from prior declarations to later definitions. Multiple assumptions are aggregated into a single comma separated string. Thus, one can provide multiple assumptions via a comma separated string, i.a., -``__attribute__((assume("assumption1,assumption2")))``. +``[[omp::assume("assumption1,assumption2")]]``. While LLVM plugins might provide more assumption strings, the default LLVM optimization passes are aware of the following assumptions: diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index 5a32463763aa..41a9745ddb57 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -10237,9 +10237,6 @@ def err_fallthrough_attr_outside_switch : Error< def err_fallthrough_attr_invalid_placement : Error< "fallthrough annotation does not directly precede switch label">; -def err_assume_attr_args : Error< - "attribute '%0' requires a single expression argument">; - def warn_unreachable_default : Warning< "default label in switch which covers all enumeration values">, InGroup, DefaultIgnore; diff --git a/clang/include/clang/Parse/Parser.h b/clang/include/clang/Parse/Parser.h index cc6d93384f80..82ed8d00c5fb 100644 --- a/clang/include/clang/Parse/Parser.h +++ b/clang/include/clang/Parse/Parser.h @@ -2997,7 +2997,8 @@ private: bool ParseCXXAssumeAttributeArg(ParsedAttributes &Attrs, IdentifierInfo *AttrName, SourceLocation AttrNameLoc, - SourceLocation *EndLoc); + SourceLocation *EndLoc, + ParsedAttr::Form Form); IdentifierInfo *TryParseCXX11AttributeIdentifier( SourceLocation &Loc, diff --git a/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp index 651ef7b78c94..fdb8c931bab8 100644 --- a/clang/lib/Parse/ParseDecl.cpp +++ b/clang/lib/Parse/ParseDecl.cpp @@ -666,6 +666,9 @@ void Parser::ParseGNUAttributeArgs( ParseBoundsAttribute(*AttrName, AttrNameLoc, Attrs, ScopeName, ScopeLoc, Form); return; + } else if (AttrKind == ParsedAttr::AT_CXXAssume) { + ParseCXXAssumeAttributeArg(Attrs, AttrName, AttrNameLoc, EndLoc, Form); + return; } // These may refer to the function arguments, but need to be parsed early to @@ -720,6 +723,10 @@ unsigned Parser::ParseClangAttributeArgs( ParseTypeTagForDatatypeAttribute(*AttrName, AttrNameLoc, Attrs, EndLoc, ScopeName, ScopeLoc, Form); break; + + case ParsedAttr::AT_CXXAssume: + ParseCXXAssumeAttributeArg(Attrs, AttrName, AttrNameLoc, EndLoc, Form); + break; } return !Attrs.empty() ? Attrs.begin()->getNumArgs() : 0; } diff --git a/clang/lib/Parse/ParseDeclCXX.cpp b/clang/lib/Parse/ParseDeclCXX.cpp index 805651e4ab06..9a4a777f575b 100644 --- a/clang/lib/Parse/ParseDeclCXX.cpp +++ b/clang/lib/Parse/ParseDeclCXX.cpp @@ -4560,7 +4560,8 @@ static bool IsBuiltInOrStandardCXX11Attribute(IdentifierInfo *AttrName, bool Parser::ParseCXXAssumeAttributeArg(ParsedAttributes &Attrs, IdentifierInfo *AttrName, SourceLocation AttrNameLoc, - SourceLocation *EndLoc) { + SourceLocation *EndLoc, + ParsedAttr::Form Form) { assert(Tok.is(tok::l_paren) && "Not a C++11 attribute argument list"); BalancedDelimiterTracker T(*this, tok::l_paren); T.consumeOpen(); @@ -4603,7 +4604,7 @@ bool Parser::ParseCXXAssumeAttributeArg(ParsedAttributes &Attrs, auto RParen = Tok.getLocation(); T.consumeClose(); Attrs.addNew(AttrName, SourceRange(AttrNameLoc, RParen), nullptr, - SourceLocation(), &Assumption, 1, ParsedAttr::Form::CXX11()); + SourceLocation(), &Assumption, 1, Form); if (EndLoc) *EndLoc = RParen; @@ -4683,7 +4684,7 @@ bool Parser::ParseCXX11AttributeArgs( ScopeName, ScopeLoc, Form); // So does C++23's assume() attribute. else if (!ScopeName && AttrName->isStr("assume")) { - if (ParseCXXAssumeAttributeArg(Attrs, AttrName, AttrNameLoc, EndLoc)) + if (ParseCXXAssumeAttributeArg(Attrs, AttrName, AttrNameLoc, EndLoc, Form)) return true; NumArgs = 1; } else diff --git a/clang/lib/Sema/SemaStmtAttr.cpp b/clang/lib/Sema/SemaStmtAttr.cpp index 36f8ecadcfab..8735d96c8407 100644 --- a/clang/lib/Sema/SemaStmtAttr.cpp +++ b/clang/lib/Sema/SemaStmtAttr.cpp @@ -665,7 +665,8 @@ bool Sema::CheckRebuiltStmtAttributes(ArrayRef Attrs) { ExprResult Sema::ActOnCXXAssumeAttr(Stmt *St, const ParsedAttr &A, SourceRange Range) { if (A.getNumArgs() != 1 || !A.getArgAsExpr(0)) { - Diag(A.getLoc(), diag::err_assume_attr_args) << A.getAttrName() << Range; + Diag(A.getLoc(), diag::err_attribute_wrong_number_arguments) + << A.getAttrName() << 1 << Range; return ExprError(); } @@ -682,8 +683,11 @@ ExprResult Sema::ActOnCXXAssumeAttr(Stmt *St, const ParsedAttr &A, Assumption = Res.get(); } - if (!getLangOpts().CPlusPlus23) + if (!getLangOpts().CPlusPlus23 && + A.getSyntax() == AttributeCommonInfo::AS_CXX11) { + llvm::dbgs() << "Syntax: " << int(A.getSyntax()) << "\n"; Diag(A.getLoc(), diag::ext_cxx23_attr) << A << Range; + } return Assumption; } diff --git a/clang/test/CodeGen/assume_attr.c b/clang/test/CodeGen/assume_attr.c deleted file mode 100644 index 338a625188af..000000000000 --- a/clang/test/CodeGen/assume_attr.c +++ /dev/null @@ -1,58 +0,0 @@ -// RUN: %clang_cc1 -emit-llvm -triple i386-linux-gnu %s -o - | FileCheck %s -// RUN: %clang_cc1 -x c -emit-pch -o %t %s -// RUN: %clang_cc1 -include-pch %t %s -emit-llvm -o - | FileCheck %s - -// TODO: for "foo" and "bar", "after" is not added as it appears "after" the first use or definition respectively. There might be a way to allow that. - -// CHECK: define{{.*}} void @bar() #0 -// CHECK: define{{.*}} void @baz() #1 -// CHECK: declare{{.*}} void @foo() #2 -// CHECK: attributes #0 -// CHECK-SAME: "llvm.assume"="bar:before1,bar:before2,bar:before3,bar:def1,bar:def2" -// CHECK: attributes #1 -// CHECK-SAME: "llvm.assume"="baz:before1,baz:before2,baz:before3,baz:def1,baz:def2,baz:after" -// CHECK: attributes #2 -// CHECK-SAME: "llvm.assume"="foo:before1,foo:before2,foo:before3" - -#ifndef HEADER -#define HEADER - -/// foo: declarations only - -__attribute__((assume("foo:before1"))) void foo(void); - -__attribute__((assume("foo:before2"))) -__attribute__((assume("foo:before3"))) void -foo(void); - -/// baz: static function declarations and a definition - -__attribute__((assume("baz:before1"))) static void baz(void); - -__attribute__((assume("baz:before2"))) -__attribute__((assume("baz:before3"))) static void -baz(void); - -// Definition -__attribute__((assume("baz:def1,baz:def2"))) static void baz(void) { foo(); } - -__attribute__((assume("baz:after"))) static void baz(void); - -/// bar: external function declarations and a definition - -__attribute__((assume("bar:before1"))) void bar(void); - -__attribute__((assume("bar:before2"))) -__attribute__((assume("bar:before3"))) void -bar(void); - -// Definition -__attribute__((assume("bar:def1,bar:def2"))) void bar(void) { baz(); } - -__attribute__((assume("bar:after"))) void bar(void); - -/// back to foo - -__attribute__((assume("foo:after"))) void foo(void); - -#endif diff --git a/clang/test/CodeGenCXX/assume_attr.cpp b/clang/test/CodeGenCXX/assume_attr.cpp index dbe76501377c..962dcc470f67 100644 --- a/clang/test/CodeGenCXX/assume_attr.cpp +++ b/clang/test/CodeGenCXX/assume_attr.cpp @@ -8,77 +8,77 @@ /// foo: declarations only -__attribute__((assume("foo:before1"))) void foo(); +[[omp::assume("foo:before1")]] void foo(); -__attribute__((assume("foo:before2"))) -__attribute__((assume("foo:before3"))) void +[[omp::assume("foo:before2")]] +[[omp::assume("foo:before3")]] void foo(); /// baz: static function declarations and a definition -__attribute__((assume("baz:before1"))) static void baz(); +[[omp::assume("baz:before1")]] static void baz(); -__attribute__((assume("baz:before2"))) -__attribute__((assume("baz:before3"))) static void +[[omp::assume("baz:before2")]] +[[omp::assume("baz:before3")]] static void baz(); // Definition -__attribute__((assume("baz:def1,baz:def2"))) static void baz() { foo(); } +[[omp::assume("baz:def1,baz:def2")]] static void baz() { foo(); } -__attribute__((assume("baz:after"))) static void baz(); +[[omp::assume("baz:after")]] static void baz(); /// bar: external function declarations and a definition -__attribute__((assume("bar:before1"))) void bar(); +[[omp::assume("bar:before1")]] void bar(); -__attribute__((assume("bar:before2"))) -__attribute__((assume("bar:before3"))) void +[[omp::assume("bar:before2")]] +[[omp::assume("bar:before3")]] void bar(); // Definition -__attribute__((assume("bar:def1,bar:def2"))) void bar() { baz(); } +[[omp::assume("bar:def1,bar:def2")]] void bar() { baz(); } -__attribute__((assume("bar:after"))) void bar(); +[[omp::assume("bar:after")]] void bar(); /// back to foo -__attribute__((assume("foo:after"))) void foo(); +[[omp::assume("foo:after")]] void foo(); /// class tests class C { - __attribute__((assume("C:private_method"))) void private_method(); - __attribute__((assume("C:private_static"))) static void private_static(); + [[omp::assume("C:private_method")]] void private_method(); + [[omp::assume("C:private_static")]] static void private_static(); public: - __attribute__((assume("C:public_method1"))) void public_method(); - __attribute__((assume("C:public_static1"))) static void public_static(); + [[omp::assume("C:public_method1")]] void public_method(); + [[omp::assume("C:public_static1")]] static void public_static(); }; -__attribute__((assume("C:public_method2"))) void C::public_method() { +[[omp::assume("C:public_method2")]] void C::public_method() { private_method(); } -__attribute__((assume("C:public_static2"))) void C::public_static() { +[[omp::assume("C:public_static2")]] void C::public_static() { private_static(); } /// template tests template -__attribute__((assume("template_func"))) void template_func() {} +[[omp::assume("template_func")]] void template_func() {} template <> -__attribute__((assume("template_func"))) void template_func() {} +[[omp::assume("template_func")]] void template_func() {} template <> void template_func() {} template struct S { - __attribute__((assume("S::method"))) void method(); + [[omp::assume("S::method")]] void method(); }; template <> -__attribute__((assume("S::method"))) void S::method() {} +[[omp::assume("S::method")]] void S::method() {} template <> void S::method() {} diff --git a/clang/test/OpenMP/assumes_codegen.cpp b/clang/test/OpenMP/assumes_codegen.cpp index 4a2518a51ec3..4206e5a9caab 100644 --- a/clang/test/OpenMP/assumes_codegen.cpp +++ b/clang/test/OpenMP/assumes_codegen.cpp @@ -67,46 +67,46 @@ int lambda_outer() { } #pragma omp end assumes -// AST: void foo() __attribute__((assume("omp_no_openmp_routines,ompx_another_warning,ompx_after_invalid_clauses"))) __attribute__((assume("omp_no_openmp"))) { -// AST-NEXT: } -// AST-NEXT: class BAR { -// AST-NEXT: public: -// AST-NEXT: __attribute__((assume("ompx_range_bar_only"))) __attribute__((assume("ompx_range_bar_only_2"))) __attribute__((assume("omp_no_openmp_routines,ompx_another_warning,ompx_after_invalid_clauses"))) __attribute__((assume("omp_no_openmp"))) BAR() { -// AST-NEXT: } -// AST-NEXT: __attribute__((assume("ompx_range_bar_only"))) __attribute__((assume("ompx_range_bar_only_2"))) __attribute__((assume("omp_no_openmp_routines,ompx_another_warning,ompx_after_invalid_clauses"))) __attribute__((assume("omp_no_openmp"))) void bar1() { -// AST-NEXT: } -// AST-NEXT: __attribute__((assume("ompx_range_bar_only"))) __attribute__((assume("ompx_range_bar_only_2"))) __attribute__((assume("omp_no_openmp_routines,ompx_another_warning,ompx_after_invalid_clauses"))) __attribute__((assume("omp_no_openmp"))) static void bar2() { -// AST-NEXT: } -// AST-NEXT: }; -// AST-NEXT: __attribute__((assume("ompx_range_bar_only"))) __attribute__((assume("ompx_range_bar_only_2"))) __attribute__((assume("omp_no_openmp_routines,ompx_another_warning,ompx_after_invalid_clauses"))) __attribute__((assume("omp_no_openmp"))) void bar() { -// AST-NEXT: BAR b; -// AST-NEXT: } -// AST-NEXT: __attribute__((assume("ompx_1234"))) __attribute__((assume("omp_no_openmp_routines,ompx_another_warning,ompx_after_invalid_clauses"))) __attribute__((assume("omp_no_openmp"))) void baz(); -// AST-NEXT: template class BAZ { -// AST-NEXT: public: -// AST-NEXT: __attribute__((assume("ompx_1234"))) __attribute__((assume("omp_no_openmp_routines,ompx_another_warning,ompx_after_invalid_clauses"))) __attribute__((assume("omp_no_openmp"))) BAZ() { -// AST-NEXT: } -// AST-NEXT: __attribute__((assume("ompx_1234"))) __attribute__((assume("omp_no_openmp_routines,ompx_another_warning,ompx_after_invalid_clauses"))) __attribute__((assume("omp_no_openmp"))) void baz1() { -// AST-NEXT: } -// AST-NEXT: __attribute__((assume("ompx_1234"))) __attribute__((assume("omp_no_openmp_routines,ompx_another_warning,ompx_after_invalid_clauses"))) __attribute__((assume("omp_no_openmp"))) static void baz2() { -// AST-NEXT: } -// AST-NEXT: }; -// AST-NEXT: template<> class BAZ { -// AST-NEXT: public: -// AST-NEXT: __attribute__((assume("ompx_1234"))) __attribute__((assume("omp_no_openmp_routines,ompx_another_warning,ompx_after_invalid_clauses"))) __attribute__((assume("omp_no_openmp"))) __attribute__((assume("omp_no_openmp_routines,ompx_another_warning,ompx_after_invalid_clauses"))) __attribute__((assume("omp_no_openmp"))) BAZ() { -// AST-NEXT: } -// AST-NEXT: __attribute__((assume("ompx_1234"))) __attribute__((assume("omp_no_openmp_routines,ompx_another_warning,ompx_after_invalid_clauses"))) __attribute__((assume("omp_no_openmp"))) __attribute__((assume("omp_no_openmp_routines,ompx_another_warning,ompx_after_invalid_clauses"))) __attribute__((assume("omp_no_openmp"))) void baz1(); -// AST-NEXT: __attribute__((assume("ompx_1234"))) __attribute__((assume("omp_no_openmp_routines,ompx_another_warning,ompx_after_invalid_clauses"))) __attribute__((assume("omp_no_openmp"))) __attribute__((assume("omp_no_openmp_routines,ompx_another_warning,ompx_after_invalid_clauses"))) __attribute__((assume("omp_no_openmp"))) static void baz2(); -// AST-NEXT: }; -// AST-NEXT: __attribute__((assume("ompx_1234"))) __attribute__((assume("omp_no_openmp_routines,ompx_another_warning,ompx_after_invalid_clauses"))) __attribute__((assume("omp_no_openmp"))) void baz() { -// AST-NEXT: BAZ b; -// AST-NEXT: } -// AST-NEXT: __attribute__((assume("ompx_lambda_assumption"))) __attribute__((assume("omp_no_openmp_routines,ompx_another_warning,ompx_after_invalid_clauses"))) __attribute__((assume("omp_no_openmp"))) int lambda_outer() { -// AST-NEXT: auto lambda_inner = []() { -// AST-NEXT: return 42; -// AST-NEXT: }; -// AST-NEXT: return lambda_inner(); -// AST-NEXT: } +// AST{LITERAL}: void foo() [[omp::assume("omp_no_openmp_routines,ompx_another_warning,ompx_after_invalid_clauses")]] [[omp::assume("omp_no_openmp")]] { +// AST-NEXT{LITERAL}: } +// AST-NEXT{LITERAL}: class BAR { +// AST-NEXT{LITERAL}: public: +// AST-NEXT{LITERAL}: [[omp::assume("ompx_range_bar_only")]] [[omp::assume("ompx_range_bar_only_2")]] [[omp::assume("omp_no_openmp_routines,ompx_another_warning,ompx_after_invalid_clauses")]] [[omp::assume("omp_no_openmp")]] BAR() { +// AST-NEXT{LITERAL}: } +// AST-NEXT{LITERAL}: [[omp::assume("ompx_range_bar_only")]] [[omp::assume("ompx_range_bar_only_2")]] [[omp::assume("omp_no_openmp_routines,ompx_another_warning,ompx_after_invalid_clauses")]] [[omp::assume("omp_no_openmp")]] void bar1() { +// AST-NEXT{LITERAL}: } +// AST-NEXT{LITERAL}: [[omp::assume("ompx_range_bar_only")]] [[omp::assume("ompx_range_bar_only_2")]] [[omp::assume("omp_no_openmp_routines,ompx_another_warning,ompx_after_invalid_clauses")]] [[omp::assume("omp_no_openmp")]] static void bar2() { +// AST-NEXT{LITERAL}: } +// AST-NEXT{LITERAL}: }; +// AST-NEXT{LITERAL}: [[omp::assume("ompx_range_bar_only")]] [[omp::assume("ompx_range_bar_only_2")]] [[omp::assume("omp_no_openmp_routines,ompx_another_warning,ompx_after_invalid_clauses")]] [[omp::assume("omp_no_openmp")]] void bar() { +// AST-NEXT{LITERAL}: BAR b; +// AST-NEXT{LITERAL}: } +// AST-NEXT{LITERAL}: [[omp::assume("ompx_1234")]] [[omp::assume("omp_no_openmp_routines,ompx_another_warning,ompx_after_invalid_clauses")]] [[omp::assume("omp_no_openmp")]] void baz(); +// AST-NEXT{LITERAL}: template class BAZ { +// AST-NEXT{LITERAL}: public: +// AST-NEXT{LITERAL}: [[omp::assume("ompx_1234")]] [[omp::assume("omp_no_openmp_routines,ompx_another_warning,ompx_after_invalid_clauses")]] [[omp::assume("omp_no_openmp")]] BAZ() { +// AST-NEXT{LITERAL}: } +// AST-NEXT{LITERAL}: [[omp::assume("ompx_1234")]] [[omp::assume("omp_no_openmp_routines,ompx_another_warning,ompx_after_invalid_clauses")]] [[omp::assume("omp_no_openmp")]] void baz1() { +// AST-NEXT{LITERAL}: } +// AST-NEXT{LITERAL}: [[omp::assume("ompx_1234")]] [[omp::assume("omp_no_openmp_routines,ompx_another_warning,ompx_after_invalid_clauses")]] [[omp::assume("omp_no_openmp")]] static void baz2() { +// AST-NEXT{LITERAL}: } +// AST-NEXT{LITERAL}: }; +// AST-NEXT{LITERAL}: template<> class BAZ { +// AST-NEXT{LITERAL}: public: +// AST-NEXT{LITERAL}: [[omp::assume("ompx_1234")]] [[omp::assume("omp_no_openmp_routines,ompx_another_warning,ompx_after_invalid_clauses")]] [[omp::assume("omp_no_openmp")]] [[omp::assume("omp_no_openmp_routines,ompx_another_warning,ompx_after_invalid_clauses")]] [[omp::assume("omp_no_openmp")]] BAZ() { +// AST-NEXT{LITERAL}: } +// AST-NEXT{LITERAL}: [[omp::assume("ompx_1234")]] [[omp::assume("omp_no_openmp_routines,ompx_another_warning,ompx_after_invalid_clauses")]] [[omp::assume("omp_no_openmp")]] [[omp::assume("omp_no_openmp_routines,ompx_another_warning,ompx_after_invalid_clauses")]] [[omp::assume("omp_no_openmp")]] void baz1(); +// AST-NEXT{LITERAL}: [[omp::assume("ompx_1234")]] [[omp::assume("omp_no_openmp_routines,ompx_another_warning,ompx_after_invalid_clauses")]] [[omp::assume("omp_no_openmp")]] [[omp::assume("omp_no_openmp_routines,ompx_another_warning,ompx_after_invalid_clauses")]] [[omp::assume("omp_no_openmp")]] static void baz2(); +// AST-NEXT{LITERAL}: }; +// AST-NEXT{LITERAL}: [[omp::assume("ompx_1234")]] [[omp::assume("omp_no_openmp_routines,ompx_another_warning,ompx_after_invalid_clauses")]] [[omp::assume("omp_no_openmp")]] void baz() { +// AST-NEXT{LITERAL}: BAZ b; +// AST-NEXT{LITERAL}: } +// AST-NEXT{LITERAL}: [[omp::assume("ompx_lambda_assumption")]] [[omp::assume("omp_no_openmp_routines,ompx_another_warning,ompx_after_invalid_clauses")]] [[omp::assume("omp_no_openmp")]] int lambda_outer() { +// AST-NEXT{LITERAL}: auto lambda_inner = []() { +// AST-NEXT{LITERAL}: return 42; +// AST-NEXT{LITERAL}: }; +// AST-NEXT{LITERAL}: return lambda_inner(); +// AST-NEXT{LITERAL}: } #endif diff --git a/clang/test/OpenMP/assumes_print.cpp b/clang/test/OpenMP/assumes_print.cpp index d8bdaaaf4518..9254c29ab833 100644 --- a/clang/test/OpenMP/assumes_print.cpp +++ b/clang/test/OpenMP/assumes_print.cpp @@ -37,8 +37,8 @@ void baz() { } #pragma omp end assumes -// CHECK: void foo() __attribute__((assume("omp_no_openmp_routines"))) __attribute__((assume("omp_no_openmp"))) -// CHECK: __attribute__((assume("ompx_range_bar_only"))) __attribute__((assume("ompx_range_bar_only_2"))) __attribute__((assume("omp_no_openmp_routines"))) __attribute__((assume("omp_no_openmp"))) void bar() -// CHECK: __attribute__((assume("ompx_1234"))) __attribute__((assume("omp_no_openmp_routines"))) __attribute__((assume("omp_no_openmp"))) void baz() +// CHECK{LITERAL}: void foo() [[omp::assume("omp_no_openmp_routines")]] [[omp::assume("omp_no_openmp")]] +// CHECK{LITERAL}: [[omp::assume("ompx_range_bar_only")]] [[omp::assume("ompx_range_bar_only_2")]] [[omp::assume("omp_no_openmp_routines")]] [[omp::assume("omp_no_openmp")]] void bar() +// CHECK{LITERAL}: [[omp::assume("ompx_1234")]] [[omp::assume("omp_no_openmp_routines")]] [[omp::assume("omp_no_openmp")]] void baz() #endif diff --git a/clang/test/OpenMP/assumes_template_print.cpp b/clang/test/OpenMP/assumes_template_print.cpp index 614138b2ee0b..f8857ffadf78 100644 --- a/clang/test/OpenMP/assumes_template_print.cpp +++ b/clang/test/OpenMP/assumes_template_print.cpp @@ -17,7 +17,7 @@ template struct S { int a; // CHECK: template struct S { -// CHECK: void foo() __attribute__((assume("ompx_global_assumption"))) { +// CHECK{LITERAL}: void foo() [[omp::assume("ompx_global_assumption")]] { void foo() { #pragma omp parallel {} @@ -25,15 +25,15 @@ struct S { }; // CHECK: template<> struct S { -// CHECK: void foo() __attribute__((assume("ompx_global_assumption"))) { +// CHECK{LITERAL}: void foo() [[omp::assume("ompx_global_assumption")]] { #pragma omp begin assumes no_openmp -// CHECK: __attribute__((assume("omp_no_openmp"))) void S_with_assumes_no_call() __attribute__((assume("ompx_global_assumption"))) { +// CHECK{LITERAL}: [[omp::assume("omp_no_openmp")]] void S_with_assumes_no_call() [[omp::assume("ompx_global_assumption")]] { void S_with_assumes_no_call() { S s; s.a = 0; } -// CHECK: __attribute__((assume("omp_no_openmp"))) void S_with_assumes_call() __attribute__((assume("ompx_global_assumption"))) { +// CHECK{LITERAL}: [[omp::assume("omp_no_openmp")]] void S_with_assumes_call() [[omp::assume("ompx_global_assumption")]] { void S_with_assumes_call() { S s; s.a = 0; @@ -42,7 +42,7 @@ void S_with_assumes_call() { } #pragma omp end assumes -// CHECK: void S_without_assumes() __attribute__((assume("ompx_global_assumption"))) { +// CHECK{LITERAL}: void S_without_assumes() [[omp::assume("ompx_global_assumption")]] { void S_without_assumes() { S s; s.foo(); @@ -54,7 +54,7 @@ void S_without_assumes() { template struct P { // CHECK: template struct P { -// CHECK: __attribute__((assume("ompx_global_assumption"))) void foo() { +// CHECK{LITERAL}: [[omp::assume("ompx_global_assumption")]] void foo() { int a; void foo() { #pragma omp parallel @@ -65,21 +65,21 @@ struct P { // TODO: Avoid the duplication here: // CHECK: template<> struct P { -// CHECK: __attribute__((assume("ompx_global_assumption"))) __attribute__((assume("ompx_global_assumption"))) void foo() { +// CHECK{LITERAL}: [[omp::assume("ompx_global_assumption")]] [[omp::assume("ompx_global_assumption")]] void foo() { -// CHECK: __attribute__((assume("ompx_global_assumption"))) void P_without_assumes() { +// CHECK{LITERAL}: [[omp::assume("ompx_global_assumption")]] void P_without_assumes() { void P_without_assumes() { P p; p.foo(); } #pragma omp begin assumes no_openmp -// CHECK: __attribute__((assume("omp_no_openmp"))) __attribute__((assume("ompx_global_assumption"))) void P_with_assumes_no_call() { +// CHECK{LITERAL}: [[omp::assume("omp_no_openmp")]] [[omp::assume("ompx_global_assumption")]] void P_with_assumes_no_call() { void P_with_assumes_no_call() { P p; p.a = 0; } -// CHECK: __attribute__((assume("omp_no_openmp"))) __attribute__((assume("ompx_global_assumption"))) void P_with_assumes_call() { +// CHECK{LITERAL}: [[omp::assume("omp_no_openmp")]] [[omp::assume("ompx_global_assumption")]] void P_with_assumes_call() { void P_with_assumes_call() { P p; p.a = 0; diff --git a/clang/test/OpenMP/remarks_parallel_in_multiple_target_state_machines.c b/clang/test/OpenMP/remarks_parallel_in_multiple_target_state_machines.c index 2f829d2ad094..1afedc6683f8 100644 --- a/clang/test/OpenMP/remarks_parallel_in_multiple_target_state_machines.c +++ b/clang/test/OpenMP/remarks_parallel_in_multiple_target_state_machines.c @@ -4,7 +4,7 @@ // host-no-diagnostics -void baz(void) __attribute__((assume("omp_no_openmp"))); +[[omp::assume("omp_no_openmp")]] void baz(void); void bar1(void) { #pragma omp parallel // #0 @@ -24,7 +24,7 @@ void foo1(void) { // all-remark@#2 {{Rewriting generic-mode kernel with a customized state machine. [OMP131]}} { - baz(); // all-remark {{Value has potential side effects preventing SPMD-mode execution. Add `__attribute__((assume("ompx_spmd_amenable")))` to the called function to override. [OMP121]}} + baz(); // all-remark {{Value has potential side effects preventing SPMD-mode execution. Add `[[omp::assume("ompx_spmd_amenable")]]` to the called function to override. [OMP121]}} #pragma omp parallel // #3 { } @@ -39,7 +39,7 @@ void foo2(void) { #pragma omp target teams // #5 // all-remark@#5 {{Rewriting generic-mode kernel with a customized state machine. [OMP131]}} { - baz(); // all-remark {{Value has potential side effects preventing SPMD-mode execution. Add `__attribute__((assume("ompx_spmd_amenable")))` to the called function to override. [OMP121]}} + baz(); // all-remark {{Value has potential side effects preventing SPMD-mode execution. Add `[[omp::assume("ompx_spmd_amenable")]]` to the called function to override. [OMP121]}} #pragma omp parallel // #6 { } @@ -57,7 +57,7 @@ void foo3(void) { #pragma omp target teams // #8 // all-remark@#8 {{Rewriting generic-mode kernel with a customized state machine. [OMP131]}} { - baz(); // all-remark {{Value has potential side effects preventing SPMD-mode execution. Add `__attribute__((assume("ompx_spmd_amenable")))` to the called function to override. [OMP121]}} + baz(); // all-remark {{Value has potential side effects preventing SPMD-mode execution. Add `[[omp::assume("ompx_spmd_amenable")]]` to the called function to override. [OMP121]}} #pragma omp parallel // #9 { } diff --git a/clang/test/OpenMP/remarks_parallel_in_target_state_machine.c b/clang/test/OpenMP/remarks_parallel_in_target_state_machine.c index c48a4b966077..5ce8f1fa4046 100644 --- a/clang/test/OpenMP/remarks_parallel_in_target_state_machine.c +++ b/clang/test/OpenMP/remarks_parallel_in_target_state_machine.c @@ -3,7 +3,7 @@ // host-no-diagnostics -void baz(void) __attribute__((assume("omp_no_openmp"))); +[[omp::assume("omp_no_openmp")]] void baz(void); void bar(void) { #pragma omp parallel // #1 \ @@ -16,7 +16,7 @@ void foo(void) { #pragma omp target teams // #2 // expected-remark@#2 {{Rewriting generic-mode kernel with a customized state machine. [OMP131]}} { - baz(); // expected-remark {{Value has potential side effects preventing SPMD-mode execution. Add `__attribute__((assume("ompx_spmd_amenable")))` to the called function to override. [OMP121]}} + baz(); // expected-remark {{Value has potential side effects preventing SPMD-mode execution. Add `[[omp::assume("ompx_spmd_amenable")]]` to the called function to override. [OMP121]}} #pragma omp parallel { } diff --git a/clang/test/Sema/attr-assume.c b/clang/test/Sema/attr-assume.c deleted file mode 100644 index 98deffa3a746..000000000000 --- a/clang/test/Sema/attr-assume.c +++ /dev/null @@ -1,14 +0,0 @@ -// RUN: %clang_cc1 -triple i386-apple-darwin9 -fsyntax-only -verify %s - -void f1(void) __attribute__((assume(3))); // expected-error {{expected string literal as argument of 'assume' attribute}} -void f2(void) __attribute__((assume(int))); // expected-error {{expected string literal as argument of 'assume' attribute}} -void f3(void) __attribute__((assume(for))); // expected-error {{expected string literal as argument of 'assume' attribute}} -void f4(void) __attribute__((assume("QQQQ"))); // expected-warning {{unknown assumption string 'QQQQ'; attribute is potentially ignored}} -void f5(void) __attribute__((assume("omp_no_openmp"))); -void f6(void) __attribute__((assume("omp_noopenmp"))); // expected-warning {{unknown assumption string 'omp_noopenmp' may be misspelled; attribute is potentially ignored, did you mean 'omp_no_openmp'?}} -void f7(void) __attribute__((assume("omp_no_openmp_routine"))); // expected-warning {{unknown assumption string 'omp_no_openmp_routine' may be misspelled; attribute is potentially ignored, did you mean 'omp_no_openmp_routines'?}} -void f8(void) __attribute__((assume("omp_no_openmp1"))); // expected-warning {{unknown assumption string 'omp_no_openmp1' may be misspelled; attribute is potentially ignored, did you mean 'omp_no_openmp'?}} -void f9(void) __attribute__((assume("omp_no_openmp", "omp_no_openmp"))); // expected-error {{'assume' attribute takes one argument}} - -int g1 __attribute__((assume(0))); // expected-error {{expected string literal as argument of 'assume' attribute}} -int g2 __attribute__((assume("omp_no_openmp"))); // expected-warning {{'assume' attribute only applies to functions and Objective-C methods}} diff --git a/clang/test/SemaCXX/cxx23-assume.cpp b/clang/test/SemaCXX/cxx23-assume.cpp index e67d72ae0a99..ea71e7b25182 100644 --- a/clang/test/SemaCXX/cxx23-assume.cpp +++ b/clang/test/SemaCXX/cxx23-assume.cpp @@ -58,6 +58,11 @@ void g(int x) { [[assume(true)]] while (false) {} // expected-error {{only applies to empty statements}} [[assume(true)]] label:; // expected-error {{cannot be applied to a declaration}} [[assume(true)]] goto label; // expected-error {{only applies to empty statements}} + + // Also check variant spellings. + __attribute__((__assume__(true))); // Should not issue a warning because it doesn't use the [[]] spelling. + __attribute__((assume(true))) {}; // expected-error {{only applies to empty statements}} + [[clang::assume(true)]] {}; // expected-error {{only applies to empty statements}} } // Check that 'x' is ODR-used here. @@ -143,3 +148,13 @@ template void f() { [[assume(val)]]; // expected-error {{expression contains unexpanded parameter pack}} } + +namespace gh71858 { +int +foo (int x, int y) +{ + __attribute__((assume(x == 42))); + __attribute__((assume(++y == 43))); // expected-warning {{has side effects that will be discarded}} + return x + y; +} +} diff --git a/llvm/lib/Transforms/IPO/OpenMPOpt.cpp b/llvm/lib/Transforms/IPO/OpenMPOpt.cpp index eea9399127e8..e3a4821b8226 100644 --- a/llvm/lib/Transforms/IPO/OpenMPOpt.cpp +++ b/llvm/lib/Transforms/IPO/OpenMPOpt.cpp @@ -4238,7 +4238,7 @@ struct AAKernelInfoFunction : AAKernelInfo { ORA << "Value has potential side effects preventing SPMD-mode " "execution"; if (isa(NonCompatibleI)) { - ORA << ". Add `__attribute__((assume(\"ompx_spmd_amenable\")))` to " + ORA << ". Add `[[omp::assume(\"ompx_spmd_amenable\")]]` to " "the called function to override"; } return ORA << "."; @@ -4380,7 +4380,7 @@ struct AAKernelInfoFunction : AAKernelInfo { continue; auto Remark = [&](OptimizationRemarkAnalysis ORA) { return ORA << "Call may contain unknown parallel regions. Use " - << "`__attribute__((assume(\"omp_no_parallelism\")))` to " + << "`[[omp::assume(\"omp_no_parallelism\")]]` to " "override."; }; A.emitRemark(UnknownParallelRegionCB, diff --git a/llvm/test/Transforms/OpenMP/custom_state_machines.ll b/llvm/test/Transforms/OpenMP/custom_state_machines.ll index 34a68a3020e5..e6ddf16f0676 100644 --- a/llvm/test/Transforms/OpenMP/custom_state_machines.ll +++ b/llvm/test/Transforms/OpenMP/custom_state_machines.ll @@ -8,7 +8,7 @@ ;; void p1(void); ;; int unknown(void); ;; void unknown_pure(void) __attribute__((pure)); -;; void unknown_no_openmp(void) __attribute__((assume("omp_no_openmp"))); +;; [[omp::assume("omp_no_openmp")]] void unknown_no_openmp(void); ;; ;; int G; ;; void no_parallel_region_in_here(void) { diff --git a/llvm/test/Transforms/OpenMP/custom_state_machines_pre_lto.ll b/llvm/test/Transforms/OpenMP/custom_state_machines_pre_lto.ll index 85d495f45039..d20821d45036 100644 --- a/llvm/test/Transforms/OpenMP/custom_state_machines_pre_lto.ll +++ b/llvm/test/Transforms/OpenMP/custom_state_machines_pre_lto.ll @@ -10,7 +10,7 @@ ;; void p1(void); ;; int unknown(void); ;; void unknown_pure(void) __attribute__((pure)); -;; void unknown_no_openmp(void) __attribute__((assume("omp_no_openmp"))); +;; [[omp::assume("omp_no_openmp")]] void unknown_no_openmp(void); ;; ;; int G; ;; void no_parallel_region_in_here(void) { diff --git a/llvm/test/Transforms/OpenMP/custom_state_machines_remarks.ll b/llvm/test/Transforms/OpenMP/custom_state_machines_remarks.ll index f8c4e6b113c9..f7bfd3065069 100644 --- a/llvm/test/Transforms/OpenMP/custom_state_machines_remarks.ll +++ b/llvm/test/Transforms/OpenMP/custom_state_machines_remarks.ll @@ -1,10 +1,10 @@ ; RUN: opt -passes=openmp-opt -pass-remarks=openmp-opt -pass-remarks-missed=openmp-opt -pass-remarks-analysis=openmp-opt -disable-output < %s 2>&1 | FileCheck %s target triple = "nvptx64" -; CHECK: remark: llvm/test/Transforms/OpenMP/custom_state_machines_remarks.c:11:1: Generic-mode kernel is executed with a customized state machine that requires a fallback. -; CHECK: remark: llvm/test/Transforms/OpenMP/custom_state_machines_remarks.c:13:5: Call may contain unknown parallel regions. Use `__attribute__((assume("omp_no_parallelism")))` to override. -; CHECK: remark: llvm/test/Transforms/OpenMP/custom_state_machines_remarks.c:15:5: Call may contain unknown parallel regions. Use `__attribute__((assume("omp_no_parallelism")))` to override. -; CHECK: remark: llvm/test/Transforms/OpenMP/custom_state_machines_remarks.c:20:1: Rewriting generic-mode kernel with a customized state machine. +; CHECK{LITERAL}: remark: llvm/test/Transforms/OpenMP/custom_state_machines_remarks.c:11:1: Generic-mode kernel is executed with a customized state machine that requires a fallback. +; CHECK{LITERAL}: remark: llvm/test/Transforms/OpenMP/custom_state_machines_remarks.c:13:5: Call may contain unknown parallel regions. Use `[[omp::assume("omp_no_parallelism")]]` to override. +; CHECK{LITERAL}: remark: llvm/test/Transforms/OpenMP/custom_state_machines_remarks.c:15:5: Call may contain unknown parallel regions. Use `[[omp::assume("omp_no_parallelism")]]` to override. +; CHECK{LITERAL}: remark: llvm/test/Transforms/OpenMP/custom_state_machines_remarks.c:20:1: Rewriting generic-mode kernel with a customized state machine. ;; void unknown(void); @@ -24,7 +24,7 @@ target triple = "nvptx64" ;; } ;; } ;; -;; void no_openmp(void) __attribute__((assume("omp_no_openmp"))); +;; [[omp::assume("omp_no_openmp")]] void no_openmp(void); ;; void test_no_fallback(void) { ;; #pragma omp target teams ;; { diff --git a/llvm/test/Transforms/OpenMP/spmdization.ll b/llvm/test/Transforms/OpenMP/spmdization.ll index 159280ae62a0..393968913855 100644 --- a/llvm/test/Transforms/OpenMP/spmdization.ll +++ b/llvm/test/Transforms/OpenMP/spmdization.ll @@ -7,7 +7,7 @@ ; RUN: opt --mtriple=nvptx64-- -S -passes=openmp-opt-postlink < %s | FileCheck %s --check-prefix=NVPTX-DISABLED2 ;; void unknown(void); -;; void spmd_amenable(void) __attribute__((assume("ompx_spmd_amenable"))); +;; [[omp::assume("ompx_spmd_amenable")]] void spmd_amenable(void); ;; ;; void sequential_loop() { ;; #pragma omp target teams @@ -22,7 +22,7 @@ ;; } ;; } ;; -;; void use(__attribute__((noescape)) int *) __attribute__((assume("ompx_spmd_amenable"))); +;; [[omp::assume("ompx_spmd_amenable")]] void use(__attribute__((noescape)) int *); ;; ;; void sequential_loop_to_stack_var() { ;; #pragma omp target teams diff --git a/llvm/test/Transforms/OpenMP/spmdization_guarding.ll b/llvm/test/Transforms/OpenMP/spmdization_guarding.ll index b2e14dce94d5..bd128b7f74d7 100644 --- a/llvm/test/Transforms/OpenMP/spmdization_guarding.ll +++ b/llvm/test/Transforms/OpenMP/spmdization_guarding.ll @@ -2,8 +2,8 @@ ; RUN: opt -S -passes=openmp-opt < %s | FileCheck %s ; RUN: opt -S -passes=openmp-opt -openmp-opt-disable-spmdization < %s | FileCheck %s --check-prefix=CHECK-DISABLED ; -; void pure(void) __attribute__((pure, assume("ompx_spmd_amenable"))); -; int no_openmp(int *) __attribute__((assume("omp_no_openmp","ompx_spmd_amenable"))); +; [[omp::assume("ompx_spmd_amenable")]] void pure(void) __attribute__((pure)); +; [[omp::assume("omp_no_openmp","ompx_spmd_amenable")]] int no_openmp(int *); ; ; void sequential_loop(int *x, int N) { ; #pragma omp target teams diff --git a/llvm/test/Transforms/OpenMP/spmdization_remarks.ll b/llvm/test/Transforms/OpenMP/spmdization_remarks.ll index 28df2f524913..f5a4cea9a841 100644 --- a/llvm/test/Transforms/OpenMP/spmdization_remarks.ll +++ b/llvm/test/Transforms/OpenMP/spmdization_remarks.ll @@ -1,12 +1,12 @@ ; RUN: opt -passes=openmp-opt -pass-remarks=openmp-opt -pass-remarks-missed=openmp-opt -pass-remarks-analysis=openmp-opt -disable-output < %s 2>&1 | FileCheck %s target triple = "nvptx64" -; CHECK: remark: llvm/test/Transforms/OpenMP/spmdization_remarks.c:13:5: Value has potential side effects preventing SPMD-mode execution. Add `__attribute__((assume("ompx_spmd_amenable")))` to the called function to override. -; CHECK: remark: llvm/test/Transforms/OpenMP/spmdization_remarks.c:15:5: Value has potential side effects preventing SPMD-mode execution. Add `__attribute__((assume("ompx_spmd_amenable")))` to the called function to override. -; CHECK: remark: llvm/test/Transforms/OpenMP/spmdization_remarks.c:11:1: Generic-mode kernel is executed with a customized state machine that requires a fallback. -; CHECK: remark: llvm/test/Transforms/OpenMP/spmdization_remarks.c:13:5: Call may contain unknown parallel regions. Use `__attribute__((assume("omp_no_parallelism")))` to override. -; CHECK: remark: llvm/test/Transforms/OpenMP/spmdization_remarks.c:15:5: Call may contain unknown parallel regions. Use `__attribute__((assume("omp_no_parallelism")))` to override. -; CHECK: remark: llvm/test/Transforms/OpenMP/spmdization_remarks.c:20:1: Transformed generic-mode kernel to SPMD-mode. +; CHECK{LITERAL}: remark: llvm/test/Transforms/OpenMP/spmdization_remarks.c:13:5: Value has potential side effects preventing SPMD-mode execution. Add `[[omp::assume("ompx_spmd_amenable")]]` to the called function to override. +; CHECK{LITERAL}: remark: llvm/test/Transforms/OpenMP/spmdization_remarks.c:15:5: Value has potential side effects preventing SPMD-mode execution. Add `[[omp::assume("ompx_spmd_amenable")]]` to the called function to override. +; CHECK{LITERAL}: remark: llvm/test/Transforms/OpenMP/spmdization_remarks.c:11:1: Generic-mode kernel is executed with a customized state machine that requires a fallback. +; CHECK{LITERAL}: remark: llvm/test/Transforms/OpenMP/spmdization_remarks.c:13:5: Call may contain unknown parallel regions. Use `[[omp::assume("omp_no_parallelism")]]` to override. +; CHECK{LITERAL}: remark: llvm/test/Transforms/OpenMP/spmdization_remarks.c:15:5: Call may contain unknown parallel regions. Use `[[omp::assume("omp_no_parallelism")]]` to override. +; CHECK{LITERAL}: remark: llvm/test/Transforms/OpenMP/spmdization_remarks.c:20:1: Transformed generic-mode kernel to SPMD-mode. ;; void unknown(void); @@ -26,7 +26,7 @@ target triple = "nvptx64" ;; } ;; } ;; -;; void no_openmp(void) __attribute__((assume("omp_no_openmp"))); +;; void no_openmp(void) [[omp::assume("omp_no_openmp")]]; ;; void test_no_fallback(void) { ;; #pragma omp target teams ;; { diff --git a/openmp/docs/remarks/OMP121.rst b/openmp/docs/remarks/OMP121.rst index 88561b8a1fe1..f3ceeac7f3ab 100644 --- a/openmp/docs/remarks/OMP121.rst +++ b/openmp/docs/remarks/OMP121.rst @@ -1,6 +1,6 @@ .. _omp121: -Value has potential side effects preventing SPMD-mode execution. Add `__attribute__((assume(\"ompx_spmd_amenable\")))` to the called function to override. [OMP121] +Value has potential side effects preventing SPMD-mode execution. Add `[[omp::assume(\"ompx_spmd_amenable\")]]` to the called function to override. [OMP121] =================================================================================================================================================================== This analysis remarks indicates that a potential side-effect that cannot be @@ -42,7 +42,7 @@ or operations that cannot be executed in SPMD-mode. $ clang++ -fopenmp -fopenmp-targets=nvptx64 -O2 -Rpass-analysis=openmp-opt omp121.cpp omp121.cpp:8:13: remark: Value has potential side effects preventing SPMD-mode - execution. Add `__attribute__((assume("ompx_spmd_amenable")))` to the called function + execution. Add `[[omp::assume("ompx_spmd_amenable")]]` to the called function to override. [OMP121] int x = work(); ^ @@ -53,7 +53,7 @@ contain any code that prevents SPMD-mode execution. .. code-block:: c++ - __attribute__((assume("ompx_spmd_amenable"))) extern int work(); + [[omp::assume("ompx_spmd_amenable")]] extern int work(); void use(int x); diff --git a/openmp/docs/remarks/OMP133.rst b/openmp/docs/remarks/OMP133.rst index f025352de105..5a734479d495 100644 --- a/openmp/docs/remarks/OMP133.rst +++ b/openmp/docs/remarks/OMP133.rst @@ -1,4 +1,4 @@ -Call may contain unknown parallel regions. Use `__attribute__((assume("omp_no_parallelism")))` to override. [OMP133] +Call may contain unknown parallel regions. Use `[[omp::assume("omp_no_parallelism")]]` to override. [OMP133] ==================================================================================================================== .. _omp133: @@ -33,7 +33,7 @@ regions. This is typically coupled with the :ref:`OMP132 ` remark. $ clang++ -fopenmp -fopenmp-targets=nvptx64 -O2 -Rpass-analysis=openmp-opt omp133.cpp omp133.cpp:6:5: remark: Call may contain unknown parallel regions. Use - `__attribute__((assume("omp_no_parallelism")))` to override. [OMP133] + `[[omp::assume("omp_no_parallelism")]]` to override. [OMP133] setup(); ^ @@ -43,7 +43,7 @@ specialized state machine. .. code-block:: c++ - __attribute__((assume("omp_no_parallelism"))) extern void setup(); + [[omp::assume("omp_no_parallelism")]] extern void setup(); void foo() { diff --git a/openmp/docs/remarks/OptimizationRemarks.rst b/openmp/docs/remarks/OptimizationRemarks.rst index a29dce60e073..2c683a4376c4 100644 --- a/openmp/docs/remarks/OptimizationRemarks.rst +++ b/openmp/docs/remarks/OptimizationRemarks.rst @@ -81,7 +81,7 @@ OpenMP Remarks * - :ref:`OMP121 ` - Analysis - Value has potential side effects preventing SPMD-mode execution. Add - `__attribute__((assume(\"ompx_spmd_amenable\")))` to the called function + `[[omp::assume(\"ompx_spmd_amenable\")]]` to the called function to override. * - :ref:`OMP130 ` - Optimization @@ -96,7 +96,7 @@ OpenMP Remarks * - :ref:`OMP133 ` - Analysis - Call may contain unknown parallel regions. Use - `__attribute__((assume("omp_no_parallelism")))` to override. + `[[omp::assume("omp_no_parallelism")]]` to override. * - :ref:`OMP140 ` - Analysis - Could not internalize function. Some optimizations may not be possible. -- GitLab From dbfedc6b270256d62439271274ed2314fed9ca9c Mon Sep 17 00:00:00 2001 From: Joseph Huber Date: Wed, 22 May 2024 10:59:56 -0500 Subject: [PATCH 149/452] [Offload] Use newer CUDA API functions when dynamically loaded (#93057) Summary: CUDA does its versioning by putting a redirection in the header so the API functions remain the same while the symbol changes. These weren't being used for some functions that required it in the dynamic cuda version. These functions have newer verisons that should be used. These are fairly old as far as I'm aware so we should be able to sweep backward compatibility under the rug. --- offload/plugins-nextgen/cuda/dynamic_cuda/cuda.h | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/offload/plugins-nextgen/cuda/dynamic_cuda/cuda.h b/offload/plugins-nextgen/cuda/dynamic_cuda/cuda.h index 32031c28f879..d65e5cf61e09 100644 --- a/offload/plugins-nextgen/cuda/dynamic_cuda/cuda.h +++ b/offload/plugins-nextgen/cuda/dynamic_cuda/cuda.h @@ -16,6 +16,15 @@ #include #include +#define cuDeviceTotalMem cuDeviceTotalMem_v2 +#define cuModuleGetGlobal cuModuleGetGlobal_v2 +#define cuMemGetInfo cuMemGetInfo_v2 +#define cuMemAlloc cuMemAlloc_v2 +#define cuMemFree cuMemFree_v2 +#define cuMemAllocHost cuMemAllocHost_v2 +#define cuDevicePrimaryCtxRelease cuDevicePrimaryCtxRelease_v2 +#define cuDevicePrimaryCtxSetFlags cuDevicePrimaryCtxSetFlags_v2 + typedef int CUdevice; typedef uintptr_t CUdeviceptr; typedef struct CUmod_st *CUmodule; -- GitLab From b586149475d71440e4ef444f5df34630101bc669 Mon Sep 17 00:00:00 2001 From: Adam Siemieniuk Date: Wed, 22 May 2024 18:01:14 +0200 Subject: [PATCH 150/452] [mlir][tensor] Fold pack and unpack of empty input tensor (#92247) Extends `tensor.empty` folding patterns with pack and unpack consumers to fold away the operations when their source is empty. --- .../Dialect/Tensor/Transforms/Transforms.h | 4 +- .../Tensor/Transforms/EmptyOpPatterns.cpp | 45 ++++++++++++ mlir/test/Dialect/Tensor/canonicalize.mlir | 1 - mlir/test/Dialect/Tensor/fold-empty-op.mlir | 73 +++++++++++++++++++ 4 files changed, 120 insertions(+), 3 deletions(-) diff --git a/mlir/include/mlir/Dialect/Tensor/Transforms/Transforms.h b/mlir/include/mlir/Dialect/Tensor/Transforms/Transforms.h index e8a09c474104..dd6b0e868256 100644 --- a/mlir/include/mlir/Dialect/Tensor/Transforms/Transforms.h +++ b/mlir/include/mlir/Dialect/Tensor/Transforms/Transforms.h @@ -59,8 +59,8 @@ void populateDropRedundantInsertSliceRankExpansionPatterns( /// `tensor.collapse_shape` into other ops. void populateReassociativeReshapeFoldingPatterns(RewritePatternSet &patterns); -/// Populates `patterns` with patterns that fold tensor.empty with -/// tensor.[extract_slice|expand_shape|collapse_shape]. +/// Populates `patterns` with patterns that fold tensor.empty with its +/// consumers. /// /// If `singleUseOnly` is set to "true", only tensor.empty ops with a single /// use are folded. diff --git a/mlir/lib/Dialect/Tensor/Transforms/EmptyOpPatterns.cpp b/mlir/lib/Dialect/Tensor/Transforms/EmptyOpPatterns.cpp index 7a707e749e69..43ad0acaf742 100644 --- a/mlir/lib/Dialect/Tensor/Transforms/EmptyOpPatterns.cpp +++ b/mlir/lib/Dialect/Tensor/Transforms/EmptyOpPatterns.cpp @@ -93,6 +93,49 @@ private: bool foldSingleUseOnly = false; }; +/// tensor.empty does not define any tensor contents, so an unpadded pack +/// can be folded away. +struct FoldEmptyTensorWithPackOp : public OpRewritePattern { + using OpRewritePattern::OpRewritePattern; + + LogicalResult matchAndRewrite(PackOp packOp, + PatternRewriter &rewriter) const override { + // Check for tensor.empty source. + auto emptyOp = packOp.getSource().getDefiningOp(); + if (!emptyOp) + return failure(); + + // Check for padding. + // Packing with padding cannot be simply removed. + if (packOp.getPaddingValue()) + return rewriter.notifyMatchFailure(packOp, "expects no padding value"); + + // Replace the pack directly with its destination. + rewriter.replaceOp(packOp, packOp.getDest()); + + return success(); + } +}; + +/// tensor.empty does not define any tensor contents, so an unpack +/// can be folded away. +struct FoldEmptyTensorWithUnPackOp : public OpRewritePattern { + using OpRewritePattern::OpRewritePattern; + + LogicalResult matchAndRewrite(UnPackOp unPackOp, + PatternRewriter &rewriter) const override { + // Check for tensor.empty source. + auto emptyOp = unPackOp.getSource().getDefiningOp(); + if (!emptyOp) + return failure(); + + // Replace the unpack directly with its destination. + rewriter.replaceOp(unPackOp, unPackOp.getDest()); + + return success(); + } +}; + } // namespace void mlir::tensor::populateFoldTensorEmptyPatterns(RewritePatternSet &patterns, @@ -101,4 +144,6 @@ void mlir::tensor::populateFoldTensorEmptyPatterns(RewritePatternSet &patterns, FoldEmptyTensorWithReshapeOp, FoldEmptyTensorWithReshapeOp>( patterns.getContext(), /*benefit=*/1, foldSingleUseOnly); + patterns.add( + patterns.getContext(), /*benefit=*/1); } diff --git a/mlir/test/Dialect/Tensor/canonicalize.mlir b/mlir/test/Dialect/Tensor/canonicalize.mlir index 914e5e8b8c4b..f7fbd3834288 100644 --- a/mlir/test/Dialect/Tensor/canonicalize.mlir +++ b/mlir/test/Dialect/Tensor/canonicalize.mlir @@ -2523,4 +2523,3 @@ func.func @dim_out_of_bounds() -> vector<7xi32> { %16 = affine.vector_load %alloc_21[%c1, %c1, %dim] : memref, vector<7xi32> return %16 : vector<7xi32> } - diff --git a/mlir/test/Dialect/Tensor/fold-empty-op.mlir b/mlir/test/Dialect/Tensor/fold-empty-op.mlir index e200a4f89261..e94f6ec7ec56 100644 --- a/mlir/test/Dialect/Tensor/fold-empty-op.mlir +++ b/mlir/test/Dialect/Tensor/fold-empty-op.mlir @@ -64,6 +64,79 @@ func.func @rank_reducing_empty_tensor_extract(%sz : index, %idx : index) -> tens return %r: tensor<2xf32> } +func.func @pack_empty(%arg0: tensor<8x8x32x32xf32>) -> tensor<8x8x32x32xf32> { + %empty_unpacked = tensor.empty() : tensor<256x256xf32> + %packed = tensor.pack %empty_unpacked + inner_dims_pos = [0, 1] inner_tiles = [32, 32] + into %arg0 : tensor<256x256xf32> -> tensor<8x8x32x32xf32> + return %packed : tensor<8x8x32x32xf32> +} + +// CHECK-LABEL: func.func @pack_empty( +// CHECK-SAME: %[[T:.+]]: tensor<8x8x32x32xf32> +// CHECK-NOT: tensor.pack +// CHECK: return %[[T]] : tensor<8x8x32x32xf32> + +func.func @pack_empty_dynamic(%arg0: tensor, %dim0: index, %dim1: index) -> tensor { + %empty_unpacked = tensor.empty(%dim0, %dim1) : tensor + %packed = tensor.pack %empty_unpacked + inner_dims_pos = [0, 1] inner_tiles = [32, 32] + into %arg0 : tensor -> tensor + return %packed : tensor +} + +// CHECK-LABEL: func.func @pack_empty_dynamic( +// CHECK-SAME: %[[T:.+]]: tensor, +// CHECK-SAME: %[[DIM0:[a-zA-Z0-9_]+]]: index, +// CHECK-SAME: %[[DIM1:[a-zA-Z0-9_]+]]: index +// CHECK-NOT: tensor.pack +// CHECK: return %[[T]] : tensor + +func.func @unpack_empty(%arg0: tensor<256x256xf32>) -> tensor<256x256xf32> { + %empty_packed = tensor.empty() : tensor<8x8x32x32xf32> + %unpacked = tensor.unpack %empty_packed + inner_dims_pos = [0, 1] inner_tiles = [32, 32] + into %arg0 : tensor<8x8x32x32xf32> -> tensor<256x256xf32> + return %unpacked : tensor<256x256xf32> +} + +// CHECK-LABEL: func.func @unpack_empty( +// CHECK-SAME: %[[T:.+]]: tensor<256x256xf32> +// CHECK-NOT: tensor.unpack +// CHECK: return %[[T]] : tensor<256x256xf32> + +func.func @unpack_empty_dynamic(%arg0: tensor, %dim0: index, %dim1: index, %dim2: index, %dim3: index) -> tensor { + %empty_packed = tensor.empty(%dim0, %dim1, %dim2, %dim3) : tensor + %unpacked = tensor.unpack %empty_packed + inner_dims_pos = [0, 1] inner_tiles = [32, 32] + into %arg0 : tensor -> tensor + return %unpacked : tensor +} + +// CHECK-LABEL: func.func @unpack_empty_dynamic( +// CHECK-SAME: %[[T:.+]]: tensor, +// CHECK-SAME: %[[DIM0:[a-zA-Z0-9_]+]]: index, +// CHECK-SAME: %[[DIM1:[a-zA-Z0-9_]+]]: index, +// CHECK-SAME: %[[DIM2:[a-zA-Z0-9_]+]]: index, +// CHECK-SAME: %[[DIM3:[a-zA-Z0-9_]+]]: index +// CHECK-NOT: tensor.unpack +// CHECK: return %[[T]] : tensor + +func.func @pack_padded_empty(%arg0: tensor<8x8x32x32xf32>) -> tensor<8x8x32x32xf32> { + %pad = arith.constant 1.0 : f32 + %empty_unpacked = tensor.empty() : tensor<256x256xf32> + %packed = tensor.pack %empty_unpacked + padding_value(%pad : f32) + inner_dims_pos = [0, 1] inner_tiles = [32, 32] + into %arg0 : tensor<256x256xf32> -> tensor<8x8x32x32xf32> + return %packed : tensor<8x8x32x32xf32> +} + +// CHECK-LABEL: func.func @pack_padded_empty( +// CHECK-SAME: %[[T:.+]]: tensor<8x8x32x32xf32> +// CHECK: %[[PACK:.+]] = tensor.pack +// CHECK: return %[[PACK]] : tensor<8x8x32x32xf32> + // ----- module attributes {transform.with_named_sequence} { -- GitLab From 7c5c8b2f479fbed6afcd4072bdef76ea867577de Mon Sep 17 00:00:00 2001 From: Amir Ayupov Date: Wed, 22 May 2024 09:14:10 -0700 Subject: [PATCH 151/452] [BOLT][NFC] Move BAT::fetchParentAddress to header (#93061) Unbreak shared build after https://github.com/llvm/llvm-project/pull/91683 --- bolt/include/bolt/Profile/BoltAddressTranslation.h | 7 ++++++- bolt/lib/Profile/BoltAddressTranslation.cpp | 7 ------- 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/bolt/include/bolt/Profile/BoltAddressTranslation.h b/bolt/include/bolt/Profile/BoltAddressTranslation.h index 68b993ee363c..753310d910a7 100644 --- a/bolt/include/bolt/Profile/BoltAddressTranslation.h +++ b/bolt/include/bolt/Profile/BoltAddressTranslation.h @@ -107,7 +107,12 @@ public: /// If available, fetch the address of the hot part linked to the cold part /// at \p Address. Return 0 otherwise. - uint64_t fetchParentAddress(uint64_t Address) const; + uint64_t fetchParentAddress(uint64_t Address) const { + auto Iter = ColdPartSource.find(Address); + if (Iter == ColdPartSource.end()) + return 0; + return Iter->second; + } /// True if the input binary has a translation table we can use to convert /// addresses when aggregating profile diff --git a/bolt/lib/Profile/BoltAddressTranslation.cpp b/bolt/lib/Profile/BoltAddressTranslation.cpp index 7cfb9c132c2c..8923bee07a31 100644 --- a/bolt/lib/Profile/BoltAddressTranslation.cpp +++ b/bolt/lib/Profile/BoltAddressTranslation.cpp @@ -547,13 +547,6 @@ BoltAddressTranslation::getFallthroughsInTrace(uint64_t FuncAddress, return Res; } -uint64_t BoltAddressTranslation::fetchParentAddress(uint64_t Address) const { - auto Iter = ColdPartSource.find(Address); - if (Iter == ColdPartSource.end()) - return 0; - return Iter->second; -} - bool BoltAddressTranslation::enabledFor( llvm::object::ELFObjectFileBase *InputFile) const { for (const SectionRef &Section : InputFile->sections()) { -- GitLab From c8fc234ee28d0e2a10bd88bae391cb3e32e2ee77 Mon Sep 17 00:00:00 2001 From: shaw young <58664393+shawbyoung@users.noreply.github.com> Date: Wed, 22 May 2024 09:27:14 -0700 Subject: [PATCH 152/452] [BOLT][NFC] Eliminate uses of throwing std::map::at (#92950) Remove calls to std::unordered_map::at, std::map::at, and std::vector::at. --- .../bolt/Profile/BoltAddressTranslation.h | 4 +- bolt/lib/Core/BinaryContext.cpp | 11 +++-- bolt/lib/Core/BinaryEmitter.cpp | 4 +- bolt/lib/Core/DynoStats.cpp | 5 ++- bolt/lib/Passes/BinaryFunctionCallGraph.cpp | 4 +- bolt/lib/Passes/BinaryPasses.cpp | 39 +++++++++-------- bolt/lib/Passes/CacheMetrics.cpp | 43 ++++++++++++++----- bolt/lib/Passes/Inliner.cpp | 4 +- bolt/lib/Profile/StaleProfileMatching.cpp | 6 ++- 9 files changed, 81 insertions(+), 39 deletions(-) diff --git a/bolt/include/bolt/Profile/BoltAddressTranslation.h b/bolt/include/bolt/Profile/BoltAddressTranslation.h index 753310d910a7..dcbcd0f60114 100644 --- a/bolt/include/bolt/Profile/BoltAddressTranslation.h +++ b/bolt/include/bolt/Profile/BoltAddressTranslation.h @@ -283,7 +283,9 @@ public: /// Returns the number of basic blocks in a function. size_t getNumBasicBlocks(uint64_t OutputAddress) const { - return NumBasicBlocksMap.at(OutputAddress); + auto It = NumBasicBlocksMap.find(OutputAddress); + assert(It != NumBasicBlocksMap.end()); + return It->second; } private: diff --git a/bolt/lib/Core/BinaryContext.cpp b/bolt/lib/Core/BinaryContext.cpp index 64d160adeee8..876934b4ddf1 100644 --- a/bolt/lib/Core/BinaryContext.cpp +++ b/bolt/lib/Core/BinaryContext.cpp @@ -934,10 +934,13 @@ std::string BinaryContext::generateJumpTableName(const BinaryFunction &BF, uint64_t Offset = 0; if (const JumpTable *JT = BF.getJumpTableContainingAddress(Address)) { Offset = Address - JT->getAddress(); - auto Itr = JT->Labels.find(Offset); - if (Itr != JT->Labels.end()) - return std::string(Itr->second->getName()); - Id = JumpTableIds.at(JT->getAddress()); + auto JTLabelsIt = JT->Labels.find(Offset); + if (JTLabelsIt != JT->Labels.end()) + return std::string(JTLabelsIt->second->getName()); + + auto JTIdsIt = JumpTableIds.find(JT->getAddress()); + assert(JTIdsIt != JumpTableIds.end()); + Id = JTIdsIt->second; } else { Id = JumpTableIds[Address] = BF.JumpTables.size(); } diff --git a/bolt/lib/Core/BinaryEmitter.cpp b/bolt/lib/Core/BinaryEmitter.cpp index 6f86ddc77454..0b44acb0816f 100644 --- a/bolt/lib/Core/BinaryEmitter.cpp +++ b/bolt/lib/Core/BinaryEmitter.cpp @@ -813,7 +813,9 @@ void BinaryEmitter::emitJumpTable(const JumpTable &JT, MCSection *HotSection, // determining its destination. std::map LabelCounts; if (opts::JumpTables > JTS_SPLIT && !JT.Counts.empty()) { - MCSymbol *CurrentLabel = JT.Labels.at(0); + auto It = JT.Labels.find(0); + assert(It != JT.Labels.end()); + MCSymbol *CurrentLabel = It->second; uint64_t CurrentLabelCount = 0; for (unsigned Index = 0; Index < JT.Entries.size(); ++Index) { auto LI = JT.Labels.find(Index * JT.EntrySize); diff --git a/bolt/lib/Core/DynoStats.cpp b/bolt/lib/Core/DynoStats.cpp index 5de0f9e0d6b8..1d9818777596 100644 --- a/bolt/lib/Core/DynoStats.cpp +++ b/bolt/lib/Core/DynoStats.cpp @@ -114,8 +114,9 @@ void DynoStats::print(raw_ostream &OS, const DynoStats *Other, for (auto &Stat : llvm::reverse(SortedHistogram)) { OS << format("%20s,%'18lld", Printer->getOpcodeName(Stat.second).data(), Stat.first * opts::DynoStatsScale); - - MaxOpcodeHistogramTy MaxMultiMap = OpcodeHistogram.at(Stat.second).second; + auto It = OpcodeHistogram.find(Stat.second); + assert(It != OpcodeHistogram.end()); + MaxOpcodeHistogramTy MaxMultiMap = It->second.second; // Start with function name:BB offset with highest execution count. for (auto &Max : llvm::reverse(MaxMultiMap)) { OS << format(", %'18lld, ", Max.first * opts::DynoStatsScale) diff --git a/bolt/lib/Passes/BinaryFunctionCallGraph.cpp b/bolt/lib/Passes/BinaryFunctionCallGraph.cpp index 2373710c9edd..bbcc9751c0cb 100644 --- a/bolt/lib/Passes/BinaryFunctionCallGraph.cpp +++ b/bolt/lib/Passes/BinaryFunctionCallGraph.cpp @@ -56,7 +56,9 @@ std::deque BinaryFunctionCallGraph::buildTraversalOrder() { std::stack Worklist; for (BinaryFunction *Func : Funcs) { - const NodeId Id = FuncToNodeId.at(Func); + auto It = FuncToNodeId.find(Func); + assert(It != FuncToNodeId.end()); + const NodeId Id = It->second; Worklist.push(Id); NodeStatus[Id] = NEW; } diff --git a/bolt/lib/Passes/BinaryPasses.cpp b/bolt/lib/Passes/BinaryPasses.cpp index 11e22dea71fb..2810f723719d 100644 --- a/bolt/lib/Passes/BinaryPasses.cpp +++ b/bolt/lib/Passes/BinaryPasses.cpp @@ -1563,23 +1563,28 @@ Error PrintProgramStats::runOnFunctions(BinaryContext &BC) { const bool Ascending = opts::DynoStatsSortOrderOpt == opts::DynoStatsSortOrder::Ascending; - if (SortAll) { - llvm::stable_sort(Functions, - [Ascending, &Stats](const BinaryFunction *A, - const BinaryFunction *B) { - return Ascending ? Stats.at(A) < Stats.at(B) - : Stats.at(B) < Stats.at(A); - }); - } else { - llvm::stable_sort( - Functions, [Ascending, &Stats](const BinaryFunction *A, - const BinaryFunction *B) { - const DynoStats &StatsA = Stats.at(A); - const DynoStats &StatsB = Stats.at(B); - return Ascending ? StatsA.lessThan(StatsB, opts::PrintSortedBy) - : StatsB.lessThan(StatsA, opts::PrintSortedBy); - }); - } + std::function + DynoStatsComparator = + SortAll ? [](const DynoStats &StatsA, + const DynoStats &StatsB) { return StatsA < StatsB; } + : [](const DynoStats &StatsA, const DynoStats &StatsB) { + return StatsA.lessThan(StatsB, opts::PrintSortedBy); + }; + + llvm::stable_sort(Functions, + [Ascending, &Stats, DynoStatsComparator]( + const BinaryFunction *A, const BinaryFunction *B) { + auto StatsItr = Stats.find(A); + assert(StatsItr != Stats.end()); + const DynoStats &StatsA = StatsItr->second; + + StatsItr = Stats.find(B); + assert(StatsItr != Stats.end()); + const DynoStats &StatsB = StatsItr->second; + + return Ascending ? DynoStatsComparator(StatsA, StatsB) + : DynoStatsComparator(StatsB, StatsA); + }); BC.outs() << "BOLT-INFO: top functions sorted by "; if (SortAll) { diff --git a/bolt/lib/Passes/CacheMetrics.cpp b/bolt/lib/Passes/CacheMetrics.cpp index b02d4303110b..21b420a5c2b0 100644 --- a/bolt/lib/Passes/CacheMetrics.cpp +++ b/bolt/lib/Passes/CacheMetrics.cpp @@ -67,7 +67,20 @@ calcTSPScore(const std::vector &BinaryFunctions, for (BinaryBasicBlock *DstBB : SrcBB->successors()) { if (SrcBB != DstBB && BI->Count != BinaryBasicBlock::COUNT_NO_PROFILE) { JumpCount += BI->Count; - if (BBAddr.at(SrcBB) + BBSize.at(SrcBB) == BBAddr.at(DstBB)) + + auto BBAddrIt = BBAddr.find(SrcBB); + assert(BBAddrIt != BBAddr.end()); + uint64_t SrcBBAddr = BBAddrIt->second; + + auto BBSizeIt = BBSize.find(SrcBB); + assert(BBSizeIt != BBSize.end()); + uint64_t SrcBBSize = BBSizeIt->second; + + BBAddrIt = BBAddr.find(DstBB); + assert(BBAddrIt != BBAddr.end()); + uint64_t DstBBAddr = BBAddrIt->second; + + if (SrcBBAddr + SrcBBSize == DstBBAddr) Score += BI->Count; } ++BI; @@ -149,20 +162,28 @@ double expectedCacheHitRatio( for (BinaryFunction *BF : BinaryFunctions) { if (BF->getLayout().block_empty()) continue; - const uint64_t Page = - BBAddr.at(BF->getLayout().block_front()) / ITLBPageSize; - PageSamples[Page] += FunctionSamples.at(BF); + auto BBAddrIt = BBAddr.find(BF->getLayout().block_front()); + assert(BBAddrIt != BBAddr.end()); + const uint64_t Page = BBAddrIt->second / ITLBPageSize; + + auto FunctionSamplesIt = FunctionSamples.find(BF); + assert(FunctionSamplesIt != FunctionSamples.end()); + PageSamples[Page] += FunctionSamplesIt->second; } // Computing the expected number of misses for every function double Misses = 0; for (BinaryFunction *BF : BinaryFunctions) { // Skip the function if it has no samples - if (BF->getLayout().block_empty() || FunctionSamples.at(BF) == 0.0) + auto FunctionSamplesIt = FunctionSamples.find(BF); + assert(FunctionSamplesIt != FunctionSamples.end()); + double Samples = FunctionSamplesIt->second; + if (BF->getLayout().block_empty() || Samples == 0.0) continue; - double Samples = FunctionSamples.at(BF); - const uint64_t Page = - BBAddr.at(BF->getLayout().block_front()) / ITLBPageSize; + + auto BBAddrIt = BBAddr.find(BF->getLayout().block_front()); + assert(BBAddrIt != BBAddr.end()); + const uint64_t Page = BBAddrIt->second / ITLBPageSize; // The probability that the page is not present in the cache const double MissProb = pow(1.0 - PageSamples[Page] / TotalSamples, ITLBEntries); @@ -170,8 +191,10 @@ double expectedCacheHitRatio( // Processing all callers of the function for (std::pair Pair : Calls[BF]) { BinaryFunction *SrcFunction = Pair.first; - const uint64_t SrcPage = - BBAddr.at(SrcFunction->getLayout().block_front()) / ITLBPageSize; + + BBAddrIt = BBAddr.find(SrcFunction->getLayout().block_front()); + assert(BBAddrIt != BBAddr.end()); + const uint64_t SrcPage = BBAddrIt->second / ITLBPageSize; // Is this a 'long' or a 'short' call? if (Page != SrcPage) { // This is a miss diff --git a/bolt/lib/Passes/Inliner.cpp b/bolt/lib/Passes/Inliner.cpp index 84e7d97067b0..f004a8eeea18 100644 --- a/bolt/lib/Passes/Inliner.cpp +++ b/bolt/lib/Passes/Inliner.cpp @@ -355,7 +355,9 @@ Inliner::inlineCall(BinaryBasicBlock &CallerBB, std::vector Successors(BB.succ_size()); llvm::transform(BB.successors(), Successors.begin(), [&InlinedBBMap](const BinaryBasicBlock *BB) { - return InlinedBBMap.at(BB); + auto It = InlinedBBMap.find(BB); + assert(It != InlinedBBMap.end()); + return It->second; }); if (CallerFunction.hasValidProfile() && Callee.hasValidProfile()) diff --git a/bolt/lib/Profile/StaleProfileMatching.cpp b/bolt/lib/Profile/StaleProfileMatching.cpp index 016962ff34d8..80c3c072e4ce 100644 --- a/bolt/lib/Profile/StaleProfileMatching.cpp +++ b/bolt/lib/Profile/StaleProfileMatching.cpp @@ -372,8 +372,10 @@ createFlowFunction(const BinaryFunction::BasicBlockOrderType &BlockOrder) { // Create necessary metadata for the flow function for (FlowJump &Jump : Func.Jumps) { - Func.Blocks.at(Jump.Source).SuccJumps.push_back(&Jump); - Func.Blocks.at(Jump.Target).PredJumps.push_back(&Jump); + assert(Jump.Source < Func.Blocks.size()); + Func.Blocks[Jump.Source].SuccJumps.push_back(&Jump); + assert(Jump.Target < Func.Blocks.size()); + Func.Blocks[Jump.Target].PredJumps.push_back(&Jump); } return Func; } -- GitLab From 37e4945a8ac26fbeccb1626dbc4a1ffa7b5825d6 Mon Sep 17 00:00:00 2001 From: Amir Ayupov Date: Wed, 22 May 2024 09:32:06 -0700 Subject: [PATCH 153/452] [BOLT][NFC] Clean up MCF (#93065) Drop unimplemented solveMCF and remnants of it. --- bolt/include/bolt/Passes/MCF.h | 24 ------------------------ bolt/lib/Passes/MCF.cpp | 13 ------------- 2 files changed, 37 deletions(-) diff --git a/bolt/include/bolt/Passes/MCF.h b/bolt/include/bolt/Passes/MCF.h index feac7f88ac11..4b87401498fa 100644 --- a/bolt/include/bolt/Passes/MCF.h +++ b/bolt/include/bolt/Passes/MCF.h @@ -15,14 +15,6 @@ namespace bolt { class BinaryFunction; class DataflowInfoManager; -enum MCFCostFunction : char { - MCF_DISABLE = 0, - MCF_LINEAR, - MCF_QUADRATIC, - MCF_LOG, - MCF_BLAMEFTS -}; - /// Implement the idea in "SamplePGO - The Power of Profile Guided Optimizations /// without the Usability Burden" by Diego Novillo to make basic block counts /// equal if we show that A dominates B, B post-dominates A and they are in the @@ -33,22 +25,6 @@ void equalizeBBCounts(DataflowInfoManager &Info, BinaryFunction &BF); /// we only have bb count. void estimateEdgeCounts(BinaryFunction &BF); -/// Entry point for computing a min-cost flow for the CFG with the goal -/// of fixing the flow of the CFG edges, that is, making sure it obeys the -/// flow-conservation equation SumInEdges = SumOutEdges. -/// -/// To do this, we create an instance of the min-cost flow problem in a -/// similar way as the one discussed in the work of Roy Levin "Completing -/// Incomplete Edge Profile by Applying Minimum Cost Circulation Algorithms". -/// We do a few things differently, though. We don't populate edge counts using -/// weights coming from a static branch prediction technique and we don't -/// use the same cost function. -/// -/// If cost function BlameFTs is used, assign all remaining flow to -/// fall-throughs. This is used when the sampling is based on taken branches -/// that do not account for them. -void solveMCF(BinaryFunction &BF, MCFCostFunction CostFunction); - } // end namespace bolt } // end namespace llvm diff --git a/bolt/lib/Passes/MCF.cpp b/bolt/lib/Passes/MCF.cpp index c3898d2dce98..b2723cd8dcb8 100644 --- a/bolt/lib/Passes/MCF.cpp +++ b/bolt/lib/Passes/MCF.cpp @@ -29,19 +29,10 @@ namespace opts { extern cl::OptionCategory BoltOptCategory; -extern cl::opt TimeOpts; - static cl::opt IterativeGuess( "iterative-guess", cl::desc("in non-LBR mode, guess edge counts using iterative technique"), cl::Hidden, cl::cat(BoltOptCategory)); - -static cl::opt UseRArcs( - "mcf-use-rarcs", - cl::desc("in MCF, consider the possibility of cancelling flow to balance " - "edges"), - cl::Hidden, cl::cat(BoltOptCategory)); - } // namespace opts namespace llvm { @@ -462,9 +453,5 @@ void estimateEdgeCounts(BinaryFunction &BF) { recalculateBBCounts(BF, /*AllEdges=*/false); } -void solveMCF(BinaryFunction &BF, MCFCostFunction CostFunction) { - llvm_unreachable("not implemented"); -} - } // namespace bolt } // namespace llvm -- GitLab From 4ea21a0261cd8599a9ffa15f5c554ab0d4bbbe27 Mon Sep 17 00:00:00 2001 From: Sirraide Date: Wed, 22 May 2024 18:32:25 +0200 Subject: [PATCH 154/452] [Clang] [NFC] Add release note about libstdc++ bug (#93059) Adding a release note about this as discussed in #92439. --------- Co-authored-by: cor3ntin --- clang/docs/ReleaseNotes.rst | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 93b6ba59ecf9..2b35e2162ab5 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -59,6 +59,18 @@ C++ Specific Potentially Breaking Changes - Clang now performs semantic analysis for unary operators with dependent operands that are known to be of non-class non-enumeration type prior to instantiation. + This change uncovered a bug in libstdc++ 14.1.0 which may cause compile failures + on systems using that version of libstdc++ and Clang 19, with an error that looks + something like this: + + .. code-block:: text + + :4:5: error: expression is not assignable + 4 | ++this; + | ^ ~~~~ + + To fix this, update libstdc++ to version 14.1.1 or greater. + ABI Changes in This Version --------------------------- - Fixed Microsoft name mangling of implicitly defined variables used for thread -- GitLab From e8dd4df72bb5f63a235359d46d7825fe46761ed2 Mon Sep 17 00:00:00 2001 From: Tyler Lanphear Date: Wed, 22 May 2024 09:44:10 -0700 Subject: [PATCH 155/452] [NFC][TTI] Mark `getReplicationShuffleCost()` as `const` (#92194) --- llvm/include/llvm/Analysis/TargetTransformInfo.h | 2 +- llvm/lib/Analysis/TargetTransformInfo.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/llvm/include/llvm/Analysis/TargetTransformInfo.h b/llvm/include/llvm/Analysis/TargetTransformInfo.h index 0c3a6b3742c7..cefce93f9e25 100644 --- a/llvm/include/llvm/Analysis/TargetTransformInfo.h +++ b/llvm/include/llvm/Analysis/TargetTransformInfo.h @@ -1397,7 +1397,7 @@ public: InstructionCost getReplicationShuffleCost(Type *EltTy, int ReplicationFactor, int VF, const APInt &DemandedDstElts, - TTI::TargetCostKind CostKind); + TTI::TargetCostKind CostKind) const; /// \return The cost of Load and Store instructions. InstructionCost diff --git a/llvm/lib/Analysis/TargetTransformInfo.cpp b/llvm/lib/Analysis/TargetTransformInfo.cpp index f6a458f7ded4..82b6d7e7c483 100644 --- a/llvm/lib/Analysis/TargetTransformInfo.cpp +++ b/llvm/lib/Analysis/TargetTransformInfo.cpp @@ -1037,7 +1037,7 @@ TargetTransformInfo::getVectorInstrCost(const Instruction &I, Type *Val, InstructionCost TargetTransformInfo::getReplicationShuffleCost( Type *EltTy, int ReplicationFactor, int VF, const APInt &DemandedDstElts, - TTI::TargetCostKind CostKind) { + TTI::TargetCostKind CostKind) const { InstructionCost Cost = TTIImpl->getReplicationShuffleCost( EltTy, ReplicationFactor, VF, DemandedDstElts, CostKind); assert(Cost >= 0 && "TTI should not produce negative costs!"); -- GitLab From 271eb0686b7b0f9d2e016751399b948ccbbe7925 Mon Sep 17 00:00:00 2001 From: Heejin Ahn Date: Wed, 22 May 2024 09:47:54 -0700 Subject: [PATCH 156/452] [WebAssembly] Upstream misc. EH changes (#92990) This upstreams more recent, mostly EH changes from libcxx and libcxxabi: - `__cxa_init_primary_exception`-related changes made when updating to LLVM 18.1.2 (https://github.com/emscripten-core/emscripten/pull/21638) - Removes ctype macros (https://github.com/emscripten-core/emscripten/pull/20960) - Guard destructor changes with `__wasm__` (https://github.com/emscripten-core/emscripten/pull/21974) --- libcxx/include/__exception/exception_ptr.h | 17 ++++++++++++++--- libcxx/include/__locale | 4 ++-- libcxxabi/include/cxxabi.h | 8 ++++++-- libcxxabi/src/cxa_exception.cpp | 7 ++++++- libcxxabi/src/cxa_exception.h | 2 +- 5 files changed, 29 insertions(+), 9 deletions(-) diff --git a/libcxx/include/__exception/exception_ptr.h b/libcxx/include/__exception/exception_ptr.h index c9027de9238c..868fd7c01533 100644 --- a/libcxx/include/__exception/exception_ptr.h +++ b/libcxx/include/__exception/exception_ptr.h @@ -38,11 +38,14 @@ struct __cxa_exception; _LIBCPP_OVERRIDABLE_FUNC_VIS __cxa_exception* __cxa_init_primary_exception( void*, std::type_info*, - void( # if defined(_WIN32) - __thiscall + void(__thiscall*)(void*)) throw(); +# elif defined(__wasm__) + // In Wasm, a destructor returns its argument + void* (*)(void*)) throw(); +# else + void (*)(void*)) throw(); # endif - *)(void*)) throw(); } } // namespace __cxxabiv1 @@ -92,8 +95,16 @@ _LIBCPP_HIDE_FROM_ABI exception_ptr make_exception_ptr(_Ep __e) _NOEXCEPT { using _Ep2 = __decay_t<_Ep>; void* __ex = __cxxabiv1::__cxa_allocate_exception(sizeof(_Ep)); +# ifdef __wasm__ + // In Wasm, a destructor returns its argument + (void)__cxxabiv1::__cxa_init_primary_exception(__ex, const_cast(&typeid(_Ep)), [](void* __p) -> void* { +# else (void)__cxxabiv1::__cxa_init_primary_exception(__ex, const_cast(&typeid(_Ep)), [](void* __p) { +# endif std::__destroy_at(static_cast<_Ep2*>(__p)); +# ifdef __wasm__ + return __p; +# endif }); try { diff --git a/libcxx/include/__locale b/libcxx/include/__locale index 36ac099d650e..1e97c7594c8b 100644 --- a/libcxx/include/__locale +++ b/libcxx/include/__locale @@ -343,12 +343,12 @@ public: static const mask __regex_word = 0x4000; // 0x8000 and 0x0100 and 0x00ff are used # define _LIBCPP_CTYPE_MASK_IS_COMPOSITE_PRINT # define _LIBCPP_CTYPE_MASK_IS_COMPOSITE_ALPHA -#elif defined(__APPLE__) || defined(__FreeBSD__) || defined(__EMSCRIPTEN__) || defined(__NetBSD__) +#elif defined(__APPLE__) || defined(__FreeBSD__) || defined(__NetBSD__) # ifdef __APPLE__ typedef __uint32_t mask; # elif defined(__FreeBSD__) typedef unsigned long mask; -# elif defined(__EMSCRIPTEN__) || defined(__NetBSD__) +# elif defined(__NetBSD__) typedef unsigned short mask; # endif static const mask space = _CTYPE_S; diff --git a/libcxxabi/include/cxxabi.h b/libcxxabi/include/cxxabi.h index 9d9beecf751f..0e3969084e04 100644 --- a/libcxxabi/include/cxxabi.h +++ b/libcxxabi/include/cxxabi.h @@ -48,13 +48,17 @@ extern _LIBCXXABI_FUNC_VIS void __cxa_free_exception(void *thrown_exception) throw(); // This function is an LLVM extension, which mirrors the same extension in libsupc++ and libcxxrt extern _LIBCXXABI_FUNC_VIS __cxa_exception* +#ifdef __wasm__ +// In Wasm, a destructor returns its argument +__cxa_init_primary_exception(void* object, std::type_info* tinfo, void*(_LIBCXXABI_DTOR_FUNC* dest)(void*)) throw(); +#else __cxa_init_primary_exception(void* object, std::type_info* tinfo, void(_LIBCXXABI_DTOR_FUNC* dest)(void*)) throw(); +#endif // 2.4.3 Throwing the Exception Object extern _LIBCXXABI_FUNC_VIS _LIBCXXABI_NORETURN void __cxa_throw(void *thrown_exception, std::type_info *tinfo, -#ifdef __WASM_EXCEPTIONS__ - // In Wasm, a destructor returns its argument +#ifdef __wasm__ void *(_LIBCXXABI_DTOR_FUNC *dest)(void *)); #else void (_LIBCXXABI_DTOR_FUNC *dest)(void *)); diff --git a/libcxxabi/src/cxa_exception.cpp b/libcxxabi/src/cxa_exception.cpp index 3141d50a6bb9..ff69a4c65e46 100644 --- a/libcxxabi/src/cxa_exception.cpp +++ b/libcxxabi/src/cxa_exception.cpp @@ -207,7 +207,12 @@ void __cxa_free_exception(void *thrown_object) throw() { } __cxa_exception* __cxa_init_primary_exception(void* object, std::type_info* tinfo, +#ifdef __wasm__ +// In Wasm, a destructor returns its argument + void *(_LIBCXXABI_DTOR_FUNC* dest)(void*)) throw() { +#else void(_LIBCXXABI_DTOR_FUNC* dest)(void*)) throw() { +#endif __cxa_exception* exception_header = cxa_exception_from_thrown_object(object); exception_header->referenceCount = 0; exception_header->unexpectedHandler = std::get_unexpected(); @@ -267,7 +272,7 @@ will call terminate, assuming that there was no handler for the exception. */ void -#ifdef __WASM_EXCEPTIONS__ +#ifdef __wasm__ // In Wasm, a destructor returns its argument __cxa_throw(void *thrown_object, std::type_info *tinfo, void *(_LIBCXXABI_DTOR_FUNC *dest)(void *)) { #else diff --git a/libcxxabi/src/cxa_exception.h b/libcxxabi/src/cxa_exception.h index 7800b940b83f..aba08f299210 100644 --- a/libcxxabi/src/cxa_exception.h +++ b/libcxxabi/src/cxa_exception.h @@ -43,7 +43,7 @@ struct _LIBCXXABI_HIDDEN __cxa_exception { // Manage the exception object itself. std::type_info *exceptionType; -#ifdef __WASM_EXCEPTIONS__ +#ifdef __wasm__ // In Wasm, a destructor returns its argument void *(_LIBCXXABI_DTOR_FUNC *exceptionDestructor)(void *); #else -- GitLab From 6262763341fcd71a2b0708cf7485f9abd1d26ba8 Mon Sep 17 00:00:00 2001 From: Mingming Liu Date: Wed, 22 May 2024 09:52:54 -0700 Subject: [PATCH 157/452] [ThinLTO][Bitcode] Generate import type in bitcode (#87600) For distributed ThinLTO, the LTO indexing step generates combined summary for each module, and postlink pipeline reads the combined summary which stores the information for link-time optimization. This patch populates the 'import type' of a summary in bitcode, and updates bitcode reader to parse the bit correctly. --- llvm/include/llvm/Bitcode/BitcodeWriter.h | 9 ++- .../llvm/LTO/legacy/ThinLTOCodeGenerator.h | 5 +- .../llvm/Transforms/IPO/FunctionImport.h | 6 +- llvm/lib/Bitcode/Writer/BitcodeWriter.cpp | 38 ++++++++-- llvm/lib/LTO/LTO.cpp | 8 +- llvm/lib/LTO/ThinLTOCodeGenerator.cpp | 10 ++- llvm/lib/Transforms/IPO/FunctionImport.cpp | 5 +- .../ThinLTO/X86/import_callee_declaration.ll | 74 ++++++++++++++----- llvm/tools/llvm-lto/llvm-lto.cpp | 5 +- 9 files changed, 119 insertions(+), 41 deletions(-) diff --git a/llvm/include/llvm/Bitcode/BitcodeWriter.h b/llvm/include/llvm/Bitcode/BitcodeWriter.h index 248d33f4502e..a343f0e05763 100644 --- a/llvm/include/llvm/Bitcode/BitcodeWriter.h +++ b/llvm/include/llvm/Bitcode/BitcodeWriter.h @@ -102,7 +102,8 @@ class raw_ostream; void writeIndex( const ModuleSummaryIndex *Index, - const std::map *ModuleToSummariesForIndex); + const std::map *ModuleToSummariesForIndex, + const GVSummaryPtrSet *DecSummaries); }; /// Write the specified module to the specified raw output stream. @@ -147,10 +148,12 @@ class raw_ostream; /// where it will be written in a new bitcode block. This is used when /// writing the combined index file for ThinLTO. When writing a subset of the /// index for a distributed backend, provide the \p ModuleToSummariesForIndex - /// map. + /// map. \p DecSummaries specifies the set of summaries for which the + /// corresponding value should be imported as a declaration (prototype). void writeIndexToFile(const ModuleSummaryIndex &Index, raw_ostream &Out, const std::map - *ModuleToSummariesForIndex = nullptr); + *ModuleToSummariesForIndex = nullptr, + const GVSummaryPtrSet *DecSummaries = nullptr); /// If EmbedBitcode is set, save a copy of the llvm IR as data in the /// __LLVM,__bitcode section (.llvmbc on non-MacOS). diff --git a/llvm/include/llvm/LTO/legacy/ThinLTOCodeGenerator.h b/llvm/include/llvm/LTO/legacy/ThinLTOCodeGenerator.h index c450acda82ad..f1337e82485c 100644 --- a/llvm/include/llvm/LTO/legacy/ThinLTOCodeGenerator.h +++ b/llvm/include/llvm/LTO/legacy/ThinLTOCodeGenerator.h @@ -271,12 +271,13 @@ public: const lto::InputFile &File); /** - * Compute the list of summaries needed for importing into module. + * Compute the list of summaries and the subset of declaration summaries + * needed for importing into module. */ void gatherImportedSummariesForModule( Module &Module, ModuleSummaryIndex &Index, std::map &ModuleToSummariesForIndex, - const lto::InputFile &File); + GVSummaryPtrSet &DecSummaries, const lto::InputFile &File); /** * Perform internalization. Index is updated to reflect linkage changes. diff --git a/llvm/include/llvm/Transforms/IPO/FunctionImport.h b/llvm/include/llvm/Transforms/IPO/FunctionImport.h index 024bba8105b8..72a0823c6627 100644 --- a/llvm/include/llvm/Transforms/IPO/FunctionImport.h +++ b/llvm/include/llvm/Transforms/IPO/FunctionImport.h @@ -212,11 +212,15 @@ bool convertToDeclaration(GlobalValue &GV); /// \p ModuleToSummariesForIndex will be populated with the needed summaries /// from each required module path. Use a std::map instead of StringMap to get /// stable order for bitcode emission. +/// +/// \p DecSummaries will be popluated with the subset of of summary pointers +/// that have 'declaration' import type among all summaries the module need. void gatherImportedSummariesForModule( StringRef ModulePath, const DenseMap &ModuleToDefinedGVSummaries, const FunctionImporter::ImportMapTy &ImportList, - std::map &ModuleToSummariesForIndex); + std::map &ModuleToSummariesForIndex, + GVSummaryPtrSet &DecSummaries); /// Emit into \p OutputFilename the files module \p ModulePath will import from. std::error_code EmitImportsFiles( diff --git a/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp b/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp index c4cea3d6eef2..c5fdd1116c9f 100644 --- a/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp +++ b/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp @@ -428,6 +428,11 @@ class IndexBitcodeWriter : public BitcodeWriterBase { /// The combined index to write to bitcode. const ModuleSummaryIndex &Index; + /// When writing combined summaries, provides the set of global value + /// summaries for which the value (function, function alias, etc) should be + /// imported as a declaration. + const GVSummaryPtrSet *DecSummaries = nullptr; + /// When writing a subset of the index for distributed backends, client /// provides a map of modules to the corresponding GUIDs/summaries to write. const std::map *ModuleToSummariesForIndex; @@ -452,11 +457,16 @@ public: /// Constructs a IndexBitcodeWriter object for the given combined index, /// writing to the provided \p Buffer. When writing a subset of the index /// for a distributed backend, provide a \p ModuleToSummariesForIndex map. + /// If provided, \p ModuleToDecSummaries specifies the set of summaries for + /// which the corresponding functions or aliased functions should be imported + /// as a declaration (but not definition) for each module. IndexBitcodeWriter(BitstreamWriter &Stream, StringTableBuilder &StrtabBuilder, const ModuleSummaryIndex &Index, + const GVSummaryPtrSet *DecSummaries = nullptr, const std::map *ModuleToSummariesForIndex = nullptr) : BitcodeWriterBase(Stream, StrtabBuilder), Index(Index), + DecSummaries(DecSummaries), ModuleToSummariesForIndex(ModuleToSummariesForIndex) { // Assign unique value ids to all summaries to be written, for use // in writing out the call graph edges. Save the mapping from GUID @@ -1202,7 +1212,8 @@ static uint64_t getEncodedFFlags(FunctionSummary::FFlags Flags) { // Decode the flags for GlobalValue in the summary. See getDecodedGVSummaryFlags // in BitcodeReader.cpp. -static uint64_t getEncodedGVSummaryFlags(GlobalValueSummary::GVFlags Flags) { +static uint64_t getEncodedGVSummaryFlags(GlobalValueSummary::GVFlags Flags, + bool ImportAsDecl = false) { uint64_t RawFlags = 0; RawFlags |= Flags.NotEligibleToImport; // bool @@ -1217,7 +1228,8 @@ static uint64_t getEncodedGVSummaryFlags(GlobalValueSummary::GVFlags Flags) { RawFlags |= (Flags.Visibility << 8); // 2 bits - RawFlags |= (Flags.ImportType << 10); // 1 bit + unsigned ImportType = Flags.ImportType | ImportAsDecl; + RawFlags |= (ImportType << 10); // 1 bit return RawFlags; } @@ -4543,6 +4555,12 @@ void IndexBitcodeWriter::writeCombinedGlobalValueSummary() { Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); unsigned AllocAbbrev = Stream.EmitAbbrev(std::move(Abbv)); + auto shouldImportValueAsDecl = [&](GlobalValueSummary *GVS) -> bool { + if (DecSummaries == nullptr) + return false; + return DecSummaries->contains(GVS); + }; + // The aliases are emitted as a post-pass, and will point to the value // id of the aliasee. Save them in a vector for post-processing. SmallVector Aliases; @@ -4653,7 +4671,8 @@ void IndexBitcodeWriter::writeCombinedGlobalValueSummary() { NameVals.push_back(*ValueId); assert(ModuleIdMap.count(FS->modulePath())); NameVals.push_back(ModuleIdMap[FS->modulePath()]); - NameVals.push_back(getEncodedGVSummaryFlags(FS->flags())); + NameVals.push_back( + getEncodedGVSummaryFlags(FS->flags(), shouldImportValueAsDecl(FS))); NameVals.push_back(FS->instCount()); NameVals.push_back(getEncodedFFlags(FS->fflags())); NameVals.push_back(FS->entryCount()); @@ -4702,7 +4721,8 @@ void IndexBitcodeWriter::writeCombinedGlobalValueSummary() { NameVals.push_back(AliasValueId); assert(ModuleIdMap.count(AS->modulePath())); NameVals.push_back(ModuleIdMap[AS->modulePath()]); - NameVals.push_back(getEncodedGVSummaryFlags(AS->flags())); + NameVals.push_back( + getEncodedGVSummaryFlags(AS->flags(), shouldImportValueAsDecl(AS))); auto AliaseeValueId = SummaryToValueIdMap[&AS->getAliasee()]; assert(AliaseeValueId); NameVals.push_back(AliaseeValueId); @@ -5036,8 +5056,9 @@ void BitcodeWriter::writeModule(const Module &M, void BitcodeWriter::writeIndex( const ModuleSummaryIndex *Index, - const std::map *ModuleToSummariesForIndex) { - IndexBitcodeWriter IndexWriter(*Stream, StrtabBuilder, *Index, + const std::map *ModuleToSummariesForIndex, + const GVSummaryPtrSet *DecSummaries) { + IndexBitcodeWriter IndexWriter(*Stream, StrtabBuilder, *Index, DecSummaries, ModuleToSummariesForIndex); IndexWriter.write(); } @@ -5090,12 +5111,13 @@ void IndexBitcodeWriter::write() { // index for a distributed backend, provide a \p ModuleToSummariesForIndex map. void llvm::writeIndexToFile( const ModuleSummaryIndex &Index, raw_ostream &Out, - const std::map *ModuleToSummariesForIndex) { + const std::map *ModuleToSummariesForIndex, + const GVSummaryPtrSet *DecSummaries) { SmallVector Buffer; Buffer.reserve(256 * 1024); BitcodeWriter Writer(Buffer); - Writer.writeIndex(&Index, ModuleToSummariesForIndex); + Writer.writeIndex(&Index, ModuleToSummariesForIndex, DecSummaries); Writer.writeStrtab(); Out.write((char *)&Buffer.front(), Buffer.size()); diff --git a/llvm/lib/LTO/LTO.cpp b/llvm/lib/LTO/LTO.cpp index e2754d74979e..7304eab738ce 100644 --- a/llvm/lib/LTO/LTO.cpp +++ b/llvm/lib/LTO/LTO.cpp @@ -1400,18 +1400,20 @@ public: llvm::StringRef ModulePath, const std::string &NewModulePath) { std::map ModuleToSummariesForIndex; + GVSummaryPtrSet DeclarationSummaries; std::error_code EC; gatherImportedSummariesForModule(ModulePath, ModuleToDefinedGVSummaries, - ImportList, ModuleToSummariesForIndex); + ImportList, ModuleToSummariesForIndex, + DeclarationSummaries); raw_fd_ostream OS(NewModulePath + ".thinlto.bc", EC, sys::fs::OpenFlags::OF_None); if (EC) return errorCodeToError(EC); - // TODO: Serialize declaration bits to bitcode. - writeIndexToFile(CombinedIndex, OS, &ModuleToSummariesForIndex); + writeIndexToFile(CombinedIndex, OS, &ModuleToSummariesForIndex, + &DeclarationSummaries); if (ShouldEmitImportsFiles) { EC = EmitImportsFiles(ModulePath, NewModulePath + ".imports", diff --git a/llvm/lib/LTO/ThinLTOCodeGenerator.cpp b/llvm/lib/LTO/ThinLTOCodeGenerator.cpp index 8f517eb50dc7..b054b42b6377 100644 --- a/llvm/lib/LTO/ThinLTOCodeGenerator.cpp +++ b/llvm/lib/LTO/ThinLTOCodeGenerator.cpp @@ -766,7 +766,7 @@ void ThinLTOCodeGenerator::crossModuleImport(Module &TheModule, void ThinLTOCodeGenerator::gatherImportedSummariesForModule( Module &TheModule, ModuleSummaryIndex &Index, std::map &ModuleToSummariesForIndex, - const lto::InputFile &File) { + GVSummaryPtrSet &DecSummaries, const lto::InputFile &File) { auto ModuleCount = Index.modulePaths().size(); auto ModuleIdentifier = TheModule.getModuleIdentifier(); @@ -796,7 +796,7 @@ void ThinLTOCodeGenerator::gatherImportedSummariesForModule( llvm::gatherImportedSummariesForModule( ModuleIdentifier, ModuleToDefinedGVSummaries, - ImportLists[ModuleIdentifier], ModuleToSummariesForIndex); + ImportLists[ModuleIdentifier], ModuleToSummariesForIndex, DecSummaries); } /** @@ -832,10 +832,14 @@ void ThinLTOCodeGenerator::emitImports(Module &TheModule, StringRef OutputName, IsPrevailing(PrevailingCopy), ImportLists, ExportLists); + // 'EmitImportsFiles' emits the list of modules from which to import from, and + // the set of keys in `ModuleToSummariesForIndex` should be a superset of keys + // in `DecSummaries`, so no need to use `DecSummaries` in `EmitImportFiles`. + GVSummaryPtrSet DecSummaries; std::map ModuleToSummariesForIndex; llvm::gatherImportedSummariesForModule( ModuleIdentifier, ModuleToDefinedGVSummaries, - ImportLists[ModuleIdentifier], ModuleToSummariesForIndex); + ImportLists[ModuleIdentifier], ModuleToSummariesForIndex, DecSummaries); std::error_code EC; if ((EC = EmitImportsFiles(ModuleIdentifier, OutputName, diff --git a/llvm/lib/Transforms/IPO/FunctionImport.cpp b/llvm/lib/Transforms/IPO/FunctionImport.cpp index a116fd653534..cb19bf2a4ae1 100644 --- a/llvm/lib/Transforms/IPO/FunctionImport.cpp +++ b/llvm/lib/Transforms/IPO/FunctionImport.cpp @@ -1435,7 +1435,8 @@ void llvm::gatherImportedSummariesForModule( StringRef ModulePath, const DenseMap &ModuleToDefinedGVSummaries, const FunctionImporter::ImportMapTy &ImportList, - std::map &ModuleToSummariesForIndex) { + std::map &ModuleToSummariesForIndex, + GVSummaryPtrSet &DecSummaries) { // Include all summaries from the importing module. ModuleToSummariesForIndex[std::string(ModulePath)] = ModuleToDefinedGVSummaries.lookup(ModulePath); @@ -1450,7 +1451,7 @@ void llvm::gatherImportedSummariesForModule( assert(DS != DefinedGVSummaries.end() && "Expected a defined summary for imported global value"); if (Type == GlobalValueSummary::Declaration) - continue; + DecSummaries.insert(DS->second); SummariesForIndex[GUID] = DS->second; } diff --git a/llvm/test/ThinLTO/X86/import_callee_declaration.ll b/llvm/test/ThinLTO/X86/import_callee_declaration.ll index 43214e3cf941..246920e5db0d 100644 --- a/llvm/test/ThinLTO/X86/import_callee_declaration.ll +++ b/llvm/test/ThinLTO/X86/import_callee_declaration.ll @@ -15,16 +15,20 @@ ; and the other one is larger. Both callees of 'small_func' are defined in lib.ll. ; - Given the import limit, in main's combined summary, the import type of 'small_func' ; and 'small_indirect_callee' will be 'definition', and the import type of -; 'large_func' and 'large_indirect_callee' will be 'declaration'. +; large* functions and their aliasees will be 'declaration'. ; ; The test will disassemble combined summaries and check the import type is ; correct. Right now postlink optimizer pipeline doesn't do anything (e.g., ; import the declaration or de-serialize summary attributes yet) so there is ; nothing to test more than the summary content. ; +; TODO: Extend this test case to test IR once postlink optimizer makes use of +; the import type for declarations. +; ; RUN: llvm-lto2 run \ ; RUN: -debug-only=function-import \ ; RUN: -import-instr-limit=7 \ +; RUN: -import-instr-evolution-factor=1.0 \ ; RUN: -import-declaration \ ; RUN: -thinlto-distributed-indexes \ ; RUN: -r=main.bc,main,px \ @@ -32,36 +36,45 @@ ; RUN: -r=main.bc,large_func, \ ; RUN: -r=lib.bc,callee,pl \ ; RUN: -r=lib.bc,large_indirect_callee,px \ +; RUN: -r=lib.bc,large_indirect_bar,px \ ; RUN: -r=lib.bc,small_func,px \ ; RUN: -r=lib.bc,large_func,px \ ; RUN: -r=lib.bc,large_indirect_callee_alias,px \ -; RUN: -r=lib.bc,calleeAddrs,px -o summary main.bc lib.bc 2>&1 | FileCheck %s --check-prefix=DUMP +; RUN: -r=lib.bc,large_indirect_bar_alias,px \ +; RUN: -r=lib.bc,calleeAddrs,px -r=lib.bc,calleeAddrs2,px -o summary main.bc lib.bc 2>&1 | FileCheck %s --check-prefix=DUMP ; -; RUN: llvm-lto -thinlto-action=thinlink -import-declaration -import-instr-limit=7 -o combined.index.bc main.bc lib.bc -; RUN: llvm-lto -thinlto-action=distributedindexes -debug-only=function-import -import-declaration -import-instr-limit=7 -thinlto-index combined.index.bc main.bc lib.bc 2>&1 | FileCheck %s --check-prefix=DUMP +; RUN: llvm-lto -thinlto-action=thinlink -import-declaration -import-instr-limit=7 -import-instr-evolution-factor=1.0 -o combined.index.bc main.bc lib.bc +; RUN: llvm-lto -thinlto-action=distributedindexes -debug-only=function-import -import-declaration -import-instr-limit=7 -import-instr-evolution-factor=1.0 -thinlto-index combined.index.bc main.bc lib.bc 2>&1 | FileCheck %s --check-prefix=DUMP -; DUMP: - 2 function definitions and 3 function declarations imported from lib.bc +; DUMP: - 2 function definitions and 4 function declarations imported from lib.bc ; First disassemble per-module summary and find out the GUID for {large_func, large_indirect_callee}. ; ; RUN: llvm-dis lib.bc -o - | FileCheck %s --check-prefix=LIB-DIS -; LIB-DIS: [[LARGEFUNC:\^[0-9]+]] = gv: (name: "large_func", summaries: {{.*}}) ; guid = 2418497564662708935 +; LIB-DIS: module: (path: "lib.bc", hash: (0, 0, 0, 0, 0)) +; LIB-DIS: gv: (name: "large_func", summaries: {{.*}}) ; guid = 2418497564662708935 +; LIB-DIS: gv: (name: "large_indirect_bar_alias", summaries: {{.*}}, aliasee: [[LARGEINDIRECT_BAR:\^[0-9]+]]{{.*}}guid = 13590951773474913315 +; LIB-DIS: [[LARGEINDIRECT_BAR]] = gv: (name: "large_indirect_bar", summaries: {{.*}}) ; guid = 13770917885399536773 ; LIB-DIS: [[LARGEINDIRECT:\^[0-9]+]] = gv: (name: "large_indirect_callee", summaries: {{.*}}) ; guid = 14343440786664691134 -; LIB-DIS: [[LARGEINDIRECTALIAS:\^[0-9]+]] = gv: (name: "large_indirect_callee_alias", summaries: {{.*}}, aliasee: [[LARGEINDIRECT]] +; LIB-DIS: gv: (name: "large_indirect_callee_alias", summaries: {{.*}}, aliasee: [[LARGEINDIRECT]]{{.*}}guid = 16730173943625350469 ; -; Secondly disassemble main's combined summary and test that large callees are -; not imported as declarations yet. +; Secondly disassemble main's combined summary and verify the import type of +; these two GUIDs are declaration. ; ; RUN: llvm-dis main.bc.thinlto.bc -o - | FileCheck %s --check-prefix=MAIN-DIS ; ; MAIN-DIS: [[LIBMOD:\^[0-9]+]] = module: (path: "lib.bc", hash: (0, 0, 0, 0, 0)) -; MAIN-DIS-NOT: [[LARGEFUNC:\^[0-9]+]] = gv: (guid: 2418497564662708935, summaries: (function: (module: [[LIBMOD]], flags: ({{.*}} importType: declaration), insts: 8, {{.*}}))) -; MAIN-DIS-NOT: [[LARGEINDIRECT:\^[0-9]+]] = gv: (guid: 14343440786664691134, summaries: (function: (module: [[LIBMOD]], flags: ({{.*}} importType: declaration), insts: 8, {{.*}}))) -; MAIN-DIS-NOT: [[LARGEINDIRECTALIAS:\^[0-9]+]] = gv: (guid: 16730173943625350469, summaries: (alias: (module: [[LIBMOD]], flags: ({{.*}} importType: declaration) +; MAIN-DIS: gv: (guid: 2418497564662708935, summaries: (function: (module: [[LIBMOD]], flags: ({{.*}} importType: declaration), insts: 8, {{.*}}))) +; When alias is imported as a copy of the aliasee, but the aliasee is not being +; imported by itself, the aliasee should be null. +; MAIN-DIS: gv: (guid: 13590951773474913315, summaries: (alias: (module: [[LIBMOD]], flags: ({{.*}} importType: declaration), aliasee: null))) +; MAIN-DIS: [[LARGEINDIRECT:\^[0-9]+]] = gv: (guid: 14343440786664691134, summaries: (function: (module: [[LIBMOD]], flags: ({{.*}} importType: declaration), insts: 8, {{.*}}))) +; MAIN-DIS: gv: (guid: 16730173943625350469, summaries: (alias: (module: [[LIBMOD]], flags: ({{.*}} importType: declaration), aliasee: [[LARGEINDIRECT]]))) ; Run in-process ThinLTO and tests that ; 1. `callee` remains internalized even if the symbols of its callers -; (large_func and large_indirect_callee) are exported as declarations and visible to main module. +; (large_func, large_indirect_callee, large_indirect_bar) are exported as +; declarations and visible to main module. ; 2. the debugging logs from `function-import` pass are expected. ; RUN: llvm-lto2 run \ @@ -69,20 +82,21 @@ ; RUN: -save-temps \ ; RUN: -thinlto-threads=1 \ ; RUN: -import-instr-limit=7 \ +; RUN: -import-instr-evolution-factor=1.0 \ ; RUN: -import-declaration \ ; RUN: -r=main.bc,main,px \ ; RUN: -r=main.bc,small_func, \ ; RUN: -r=main.bc,large_func, \ ; RUN: -r=lib.bc,callee,pl \ ; RUN: -r=lib.bc,large_indirect_callee,px \ +; RUN: -r=lib.bc,large_indirect_bar,px \ ; RUN: -r=lib.bc,small_func,px \ ; RUN: -r=lib.bc,large_func,px \ ; RUN: -r=lib.bc,large_indirect_callee_alias,px \ -; RUN: -r=lib.bc,calleeAddrs,px -o in-process main.bc lib.bc 2>&1 | FileCheck %s --check-prefix=IMPORTDUMP +; RUN: -r=lib.bc,large_indirect_bar_alias,px \ +; RUN: -r=lib.bc,calleeAddrs,px -r=lib.bc,calleeAddrs2,px -o in-process main.bc lib.bc 2>&1 | FileCheck %s --check-prefix=IMPORTDUMP -; Test import status from debugging logs. -; TODO: Serialize declaration bit and test declaration bits are correctly set, -; and extend this test case to test IR once postlink optimizer makes use of +; TODO: Extend this test case to test IR once postlink optimizer makes use of ; the import type for declarations. ; IMPORTDUMP-DAG: Not importing function 11825436545918268459 callee from lib.cc ; IMPORTDUMP-DAG: Is importing function declaration 14343440786664691134 large_indirect_callee from lib.cc @@ -91,6 +105,8 @@ ; IMPORTDUMP-DAG: Is importing function declaration 2418497564662708935 large_func from lib.cc ; IMPORTDUMP-DAG: Not importing global 7680325410415171624 calleeAddrs from lib.cc ; IMPORTDUMP-DAG: Is importing alias declaration 16730173943625350469 large_indirect_callee_alias from lib.cc +; IMPORTDUMP-DAG: Is importing alias declaration 13590951773474913315 large_indirect_bar_alias from lib.cc +; IMPORTDUMP-DAG: Not importing function 13770917885399536773 large_indirect_bar ; RUN: llvm-dis in-process.1.3.import.bc -o - | FileCheck %s --check-prefix=IMPORT @@ -101,6 +117,8 @@ ; IMPORT-DAG: declare void @large_func ; IMPORT-NOT: large_indirect_callee ; IMPORT-NOT: large_indirect_callee_alias +; IMPORT-NOT: large_indirect_bar +; IMPORT-NOT: large_indirect_bar_alias ; INTERNALIZE: define internal void @callee() @@ -124,8 +142,13 @@ source_filename = "lib.cc" target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128" target triple = "x86_64-unknown-linux-gnu" +; Both large_indirect_callee and large_indirect_callee_alias are referenced +; and visible to main.ll. @calleeAddrs = global [3 x ptr] [ptr @large_indirect_callee, ptr @small_indirect_callee, ptr @large_indirect_callee_alias] +; large_indirect_bar_alias is visible to main.ll but its aliasee isn't. +@calleeAddrs2 = global [1 x ptr] [ptr @large_indirect_bar_alias] + define void @callee() #1 { ret void } @@ -141,12 +164,28 @@ define void @large_indirect_callee()#2 { ret void } +define void @large_indirect_bar()#2 { + call void @callee() + call void @callee() + call void @callee() + call void @callee() + call void @callee() + call void @callee() + call void @callee() + ret void +} + define internal void @small_indirect_callee() #0 { +entry: + %0 = load ptr, ptr @calleeAddrs2 + call void %0(), !prof !3 ret void } @large_indirect_callee_alias = alias void(), ptr @large_indirect_callee +@large_indirect_bar_alias = alias void(), ptr @large_indirect_bar + define void @small_func() { entry: %0 = load ptr, ptr @calleeAddrs @@ -179,3 +218,4 @@ attributes #2 = { norecurse } !0 = !{!"VP", i32 0, i64 1, i64 14343440786664691134, i64 1} !1 = !{!"VP", i32 0, i64 1, i64 13568239288960714650, i64 1} !2 = !{!"VP", i32 0, i64 1, i64 16730173943625350469, i64 1} +!3 = !{!"VP", i32 0, i64 1, i64 13590951773474913315, i64 1} diff --git a/llvm/tools/llvm-lto/llvm-lto.cpp b/llvm/tools/llvm-lto/llvm-lto.cpp index f310097eec63..8218bd5a74ea 100644 --- a/llvm/tools/llvm-lto/llvm-lto.cpp +++ b/llvm/tools/llvm-lto/llvm-lto.cpp @@ -692,8 +692,9 @@ private: // Build a map of module to the GUIDs and summary objects that should // be written to its index. std::map ModuleToSummariesForIndex; + GVSummaryPtrSet DecSummaries; ThinGenerator.gatherImportedSummariesForModule( - *TheModule, *Index, ModuleToSummariesForIndex, *Input); + *TheModule, *Index, ModuleToSummariesForIndex, DecSummaries, *Input); std::string OutputName = OutputFilename; if (OutputName.empty()) { @@ -703,7 +704,7 @@ private: std::error_code EC; raw_fd_ostream OS(OutputName, EC, sys::fs::OpenFlags::OF_None); error(EC, "error opening the file '" + OutputName + "'"); - writeIndexToFile(*Index, OS, &ModuleToSummariesForIndex); + writeIndexToFile(*Index, OS, &ModuleToSummariesForIndex, &DecSummaries); } } -- GitLab From 135ddd80bedc747405bd8d93be1dd1da1bee4bcc Mon Sep 17 00:00:00 2001 From: Craig Topper Date: Wed, 22 May 2024 09:56:13 -0700 Subject: [PATCH 158/452] [X86] Remove unused MachineLoopInfo from X86FixupBWInsts. NFC (#92984) --- llvm/lib/Target/X86/X86FixupBWInsts.cpp | 7 ------- llvm/test/CodeGen/X86/opt-pipeline.ll | 2 -- 2 files changed, 9 deletions(-) diff --git a/llvm/lib/Target/X86/X86FixupBWInsts.cpp b/llvm/lib/Target/X86/X86FixupBWInsts.cpp index db1d21b59a7b..a0c91d4e3c3d 100644 --- a/llvm/lib/Target/X86/X86FixupBWInsts.cpp +++ b/llvm/lib/Target/X86/X86FixupBWInsts.cpp @@ -53,7 +53,6 @@ #include "llvm/CodeGen/LiveRegUnits.h" #include "llvm/CodeGen/MachineFunctionPass.h" #include "llvm/CodeGen/MachineInstrBuilder.h" -#include "llvm/CodeGen/MachineLoopInfo.h" #include "llvm/CodeGen/MachineRegisterInfo.h" #include "llvm/CodeGen/MachineSizeOpts.h" #include "llvm/CodeGen/Passes.h" @@ -113,8 +112,6 @@ public: FixupBWInstPass() : MachineFunctionPass(ID) { } void getAnalysisUsage(AnalysisUsage &AU) const override { - AU.addRequired(); // Machine loop info is used to - // guide some heuristics. AU.addRequired(); AU.addRequired(); MachineFunctionPass::getAnalysisUsage(AU); @@ -141,9 +138,6 @@ private: /// Local member for function's OptForSize attribute. bool OptForSize = false; - /// Machine loop info used for guiding some heruistics. - MachineLoopInfo *MLI = nullptr; - /// Register Liveness information after the current instruction. LiveRegUnits LiveUnits; @@ -164,7 +158,6 @@ bool FixupBWInstPass::runOnMachineFunction(MachineFunction &MF) { this->MF = &MF; TII = MF.getSubtarget().getInstrInfo(); TRI = MF.getRegInfo().getTargetRegisterInfo(); - MLI = &getAnalysis(); PSI = &getAnalysis().getPSI(); MBFI = (PSI && PSI->hasProfileSummary()) ? &getAnalysis().getBFI() : diff --git a/llvm/test/CodeGen/X86/opt-pipeline.ll b/llvm/test/CodeGen/X86/opt-pipeline.ll index 43589dc993da..3f57a03decd0 100644 --- a/llvm/test/CodeGen/X86/opt-pipeline.ll +++ b/llvm/test/CodeGen/X86/opt-pipeline.ll @@ -197,8 +197,6 @@ ; CHECK-NEXT: BreakFalseDeps ; CHECK-NEXT: X86 Indirect Branch Tracking ; CHECK-NEXT: X86 vzeroupper inserter -; CHECK-NEXT: MachineDominator Tree Construction -; CHECK-NEXT: Machine Natural Loop Construction ; CHECK-NEXT: Lazy Machine Block Frequency Analysis ; CHECK-NEXT: X86 Byte/Word Instruction Fixup ; CHECK-NEXT: Lazy Machine Block Frequency Analysis -- GitLab From 9f0e59f3c1a56fd14025df973c9f944010efe09a Mon Sep 17 00:00:00 2001 From: Kiran Chandramohan Date: Wed, 22 May 2024 18:02:41 +0100 Subject: [PATCH 159/452] [Flang][OpenMP] Re-enable tests on windows 2/n (#93013) Re-enables the single, symbol and threadprivate tests --- flang/test/Semantics/OpenMP/single01.f90 | 2 -- flang/test/Semantics/OpenMP/single02.f90 | 2 -- flang/test/Semantics/OpenMP/symbol01.f90 | 2 -- flang/test/Semantics/OpenMP/symbol02.f90 | 2 -- flang/test/Semantics/OpenMP/symbol03.f90 | 2 -- flang/test/Semantics/OpenMP/symbol04.f90 | 2 -- flang/test/Semantics/OpenMP/symbol05.f90 | 2 -- flang/test/Semantics/OpenMP/symbol06.f90 | 2 -- flang/test/Semantics/OpenMP/symbol07.f90 | 2 -- flang/test/Semantics/OpenMP/symbol08.f90 | 2 -- flang/test/Semantics/OpenMP/symbol09.f90 | 2 -- flang/test/Semantics/OpenMP/threadprivate01.f90 | 2 -- flang/test/Semantics/OpenMP/threadprivate02.f90 | 2 -- flang/test/Semantics/OpenMP/threadprivate03.f90 | 2 -- flang/test/Semantics/OpenMP/threadprivate04.f90 | 2 -- flang/test/Semantics/OpenMP/threadprivate05.f90 | 2 -- flang/test/Semantics/OpenMP/threadprivate06.f90 | 2 -- flang/test/Semantics/OpenMP/threadprivate07.f90 | 2 -- 18 files changed, 36 deletions(-) diff --git a/flang/test/Semantics/OpenMP/single01.f90 b/flang/test/Semantics/OpenMP/single01.f90 index 0468e695d8cf..2e40bec56e9c 100644 --- a/flang/test/Semantics/OpenMP/single01.f90 +++ b/flang/test/Semantics/OpenMP/single01.f90 @@ -1,5 +1,3 @@ -! UNSUPPORTED: system-windows -! Marking as unsupported due to suspected long runtime on Windows ! RUN: %python %S/../test_errors.py %s %flang_fc1 -fopenmp ! OpenMP Version 4.5 ! 2.7.3 single Construct diff --git a/flang/test/Semantics/OpenMP/single02.f90 b/flang/test/Semantics/OpenMP/single02.f90 index 9d9d306c2f53..03cf7fbb6ad3 100644 --- a/flang/test/Semantics/OpenMP/single02.f90 +++ b/flang/test/Semantics/OpenMP/single02.f90 @@ -1,5 +1,3 @@ -! UNSUPPORTED: system-windows -! Marking as unsupported due to suspected long runtime on Windows ! RUN: %python %S/../test_errors.py %s %flang_fc1 -fopenmp ! OpenMP Version 4.5 ! 2.7.3 single Construct diff --git a/flang/test/Semantics/OpenMP/symbol01.f90 b/flang/test/Semantics/OpenMP/symbol01.f90 index e2a9c01e9d5f..0b435a9ab985 100644 --- a/flang/test/Semantics/OpenMP/symbol01.f90 +++ b/flang/test/Semantics/OpenMP/symbol01.f90 @@ -1,5 +1,3 @@ -! UNSUPPORTED: system-windows -! Marking as unsupported due to suspected long runtime on Windows ! RUN: %python %S/../test_symbols.py %s %flang_fc1 -fopenmp ! Test clauses that accept list. diff --git a/flang/test/Semantics/OpenMP/symbol02.f90 b/flang/test/Semantics/OpenMP/symbol02.f90 index 1b1dc4489448..f6ffc5500d0a 100644 --- a/flang/test/Semantics/OpenMP/symbol02.f90 +++ b/flang/test/Semantics/OpenMP/symbol02.f90 @@ -1,5 +1,3 @@ -! UNSUPPORTED: system-windows -! Marking as unsupported due to suspected long runtime on Windows ! RUN: %python %S/../test_symbols.py %s %flang_fc1 -fopenmp ! 1.4.1 Structure of the OpenMP Memory Model diff --git a/flang/test/Semantics/OpenMP/symbol03.f90 b/flang/test/Semantics/OpenMP/symbol03.f90 index 76d93577d3ac..93e9b7a3eae6 100644 --- a/flang/test/Semantics/OpenMP/symbol03.f90 +++ b/flang/test/Semantics/OpenMP/symbol03.f90 @@ -1,5 +1,3 @@ -! UNSUPPORTED: system-windows -! Marking as unsupported due to suspected long runtime on Windows ! RUN: %python %S/../test_symbols.py %s %flang_fc1 -fopenmp ! 1.4.1 Structure of the OpenMP Memory Model diff --git a/flang/test/Semantics/OpenMP/symbol04.f90 b/flang/test/Semantics/OpenMP/symbol04.f90 index 8ef154ebbf9d..808d1e0dd09b 100644 --- a/flang/test/Semantics/OpenMP/symbol04.f90 +++ b/flang/test/Semantics/OpenMP/symbol04.f90 @@ -1,5 +1,3 @@ -! UNSUPPORTED: system-windows -! Marking as unsupported due to suspected long runtime on Windows ! RUN: %python %S/../test_symbols.py %s %flang_fc1 -fopenmp ! 2.15.3 Data-Sharing Attribute Clauses diff --git a/flang/test/Semantics/OpenMP/symbol05.f90 b/flang/test/Semantics/OpenMP/symbol05.f90 index d08d85270380..fa0a8f65a429 100644 --- a/flang/test/Semantics/OpenMP/symbol05.f90 +++ b/flang/test/Semantics/OpenMP/symbol05.f90 @@ -1,5 +1,3 @@ -! UNSUPPORTED: system-windows -! Marking as unsupported due to suspected long runtime on Windows ! RUN: %python %S/../test_symbols.py %s %flang_fc1 -fopenmp ! 2.15.2 threadprivate Directive diff --git a/flang/test/Semantics/OpenMP/symbol06.f90 b/flang/test/Semantics/OpenMP/symbol06.f90 index a2cd288dfd15..906264eb1264 100644 --- a/flang/test/Semantics/OpenMP/symbol06.f90 +++ b/flang/test/Semantics/OpenMP/symbol06.f90 @@ -1,5 +1,3 @@ -! UNSUPPORTED: system-windows -! Marking as unsupported due to suspected long runtime on Windows ! RUN: %python %S/../test_symbols.py %s %flang_fc1 -fopenmp ! 2.15.3 Data-Sharing Attribute Clauses diff --git a/flang/test/Semantics/OpenMP/symbol07.f90 b/flang/test/Semantics/OpenMP/symbol07.f90 index ee6cd2a0df2e..e2250f5c7908 100644 --- a/flang/test/Semantics/OpenMP/symbol07.f90 +++ b/flang/test/Semantics/OpenMP/symbol07.f90 @@ -1,5 +1,3 @@ -! UNSUPPORTED: system-windows -! Marking as unsupported due to suspected long runtime on Windows ! RUN: %python %S/../test_symbols.py %s %flang_fc1 -fopenmp ! Generic tests diff --git a/flang/test/Semantics/OpenMP/symbol08.f90 b/flang/test/Semantics/OpenMP/symbol08.f90 index 76db86cd54ca..3af85af74ee9 100644 --- a/flang/test/Semantics/OpenMP/symbol08.f90 +++ b/flang/test/Semantics/OpenMP/symbol08.f90 @@ -1,5 +1,3 @@ -! UNSUPPORTED: system-windows -! Marking as unsupported due to suspected long runtime on Windows ! RUN: %python %S/../test_symbols.py %s %flang_fc1 -fopenmp ! 2.15.1.1 Predetermined rules for associated do-loops index variable diff --git a/flang/test/Semantics/OpenMP/symbol09.f90 b/flang/test/Semantics/OpenMP/symbol09.f90 index ee6cd2a0df2e..e2250f5c7908 100644 --- a/flang/test/Semantics/OpenMP/symbol09.f90 +++ b/flang/test/Semantics/OpenMP/symbol09.f90 @@ -1,5 +1,3 @@ -! UNSUPPORTED: system-windows -! Marking as unsupported due to suspected long runtime on Windows ! RUN: %python %S/../test_symbols.py %s %flang_fc1 -fopenmp ! Generic tests diff --git a/flang/test/Semantics/OpenMP/threadprivate01.f90 b/flang/test/Semantics/OpenMP/threadprivate01.f90 index 6597941ac3d5..c2cf9ba99ab0 100644 --- a/flang/test/Semantics/OpenMP/threadprivate01.f90 +++ b/flang/test/Semantics/OpenMP/threadprivate01.f90 @@ -1,5 +1,3 @@ -! UNSUPPORTED: system-windows -! Marking as unsupported due to suspected long runtime on Windows ! REQUIRES: openmp_runtime ! RUN: %python %S/../test_errors.py %s %flang_fc1 %openmp_flags diff --git a/flang/test/Semantics/OpenMP/threadprivate02.f90 b/flang/test/Semantics/OpenMP/threadprivate02.f90 index 862d1e8a45c4..7f6e8dcc8e8a 100644 --- a/flang/test/Semantics/OpenMP/threadprivate02.f90 +++ b/flang/test/Semantics/OpenMP/threadprivate02.f90 @@ -1,5 +1,3 @@ -! UNSUPPORTED: system-windows -! Marking as unsupported due to suspected long runtime on Windows ! RUN: %python %S/../test_errors.py %s %flang_fc1 -fopenmp ! OpenMP Version 5.1 ! Check OpenMP construct validity for the following directives: diff --git a/flang/test/Semantics/OpenMP/threadprivate03.f90 b/flang/test/Semantics/OpenMP/threadprivate03.f90 index 57d3b9209820..b466a8e05e9c 100644 --- a/flang/test/Semantics/OpenMP/threadprivate03.f90 +++ b/flang/test/Semantics/OpenMP/threadprivate03.f90 @@ -1,5 +1,3 @@ -! UNSUPPORTED: system-windows -! Marking as unsupported due to suspected long runtime on Windows ! RUN: %python %S/../test_errors.py %s %flang_fc1 -fopenmp -pedantic ! OpenMP Version 5.1 ! Check OpenMP construct validity for the following directives: diff --git a/flang/test/Semantics/OpenMP/threadprivate04.f90 b/flang/test/Semantics/OpenMP/threadprivate04.f90 index 8199dbaea166..3d8c7fb8de8f 100644 --- a/flang/test/Semantics/OpenMP/threadprivate04.f90 +++ b/flang/test/Semantics/OpenMP/threadprivate04.f90 @@ -1,5 +1,3 @@ -! UNSUPPORTED: system-windows -! Marking as unsupported due to suspected long runtime on Windows ! RUN: %python %S/../test_errors.py %s %flang_fc1 -fopenmp ! OpenMP Version 5.1 ! Check OpenMP construct validity for the following directives: diff --git a/flang/test/Semantics/OpenMP/threadprivate05.f90 b/flang/test/Semantics/OpenMP/threadprivate05.f90 index eecf9e781cf7..cdbf3701b70a 100644 --- a/flang/test/Semantics/OpenMP/threadprivate05.f90 +++ b/flang/test/Semantics/OpenMP/threadprivate05.f90 @@ -1,5 +1,3 @@ -! UNSUPPORTED: system-windows -! Marking as unsupported due to suspected long runtime on Windows ! RUN: %python %S/../test_errors.py %s %flang_fc1 -fopenmp ! OpenMP Version 5.1 ! Check OpenMP construct validity for the following directives: diff --git a/flang/test/Semantics/OpenMP/threadprivate06.f90 b/flang/test/Semantics/OpenMP/threadprivate06.f90 index 5537a8805e9f..f31c38f6f2b2 100644 --- a/flang/test/Semantics/OpenMP/threadprivate06.f90 +++ b/flang/test/Semantics/OpenMP/threadprivate06.f90 @@ -1,5 +1,3 @@ -! UNSUPPORTED: system-windows -! Marking as unsupported due to suspected long runtime on Windows ! RUN: %python %S/../test_errors.py %s %flang_fc1 -fopenmp ! OpenMP Version 5.1 ! Check OpenMP construct validity for the following directives: diff --git a/flang/test/Semantics/OpenMP/threadprivate07.f90 b/flang/test/Semantics/OpenMP/threadprivate07.f90 index 5302fdf4ab71..c9a006ca0e08 100644 --- a/flang/test/Semantics/OpenMP/threadprivate07.f90 +++ b/flang/test/Semantics/OpenMP/threadprivate07.f90 @@ -1,5 +1,3 @@ -! UNSUPPORTED: system-windows -! Marking as unsupported due to suspected long runtime on Windows ! RUN: %python %S/../test_errors.py %s %flang_fc1 -fopenmp ! Check Threadprivate Directive with local variable of a BLOCK construct. -- GitLab From 8df5a37b848c6ac5a68b56eeddb4a7746b84d288 Mon Sep 17 00:00:00 2001 From: Kazu Hirata Date: Wed, 22 May 2024 10:09:10 -0700 Subject: [PATCH 160/452] [lldb] Fix a warning This patch fixes: lldb/source/Plugins/ABI/PowerPC/ABISysV_ppc64.cpp:839:7: error: ignoring return value of function declared with 'nodiscard' attribute [-Werror,-Wunused-result] --- lldb/source/Plugins/ABI/PowerPC/ABISysV_ppc64.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lldb/source/Plugins/ABI/PowerPC/ABISysV_ppc64.cpp b/lldb/source/Plugins/ABI/PowerPC/ABISysV_ppc64.cpp index 3d9b4566ca1c..7a6b7429fddb 100644 --- a/lldb/source/Plugins/ABI/PowerPC/ABISysV_ppc64.cpp +++ b/lldb/source/Plugins/ABI/PowerPC/ABISysV_ppc64.cpp @@ -836,7 +836,7 @@ private: for (uint32_t i = 0; i < n; i++) { std::string name; uint32_t size; - GetChildType(i, name, size); + (void)GetChildType(i, name, size); // NOTE: the offset returned by GetChildCompilerTypeAtIndex() // can't be used because it never considers alignment bytes // between struct fields. -- GitLab From f203cb03d93240cfd79e603b742006f96227a00b Mon Sep 17 00:00:00 2001 From: Aaron Ballman Date: Wed, 22 May 2024 13:17:01 -0400 Subject: [PATCH 161/452] Fix a benign typo in a test; NFC We were still matching the expected diagnostic, but this ensures we match the opening quotation mark as well. --- clang/test/CXX/expr/expr.unary/expr.sizeof/p5-0x.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clang/test/CXX/expr/expr.unary/expr.sizeof/p5-0x.cpp b/clang/test/CXX/expr/expr.unary/expr.sizeof/p5-0x.cpp index afd8ef05302f..19f90801df31 100644 --- a/clang/test/CXX/expr/expr.unary/expr.sizeof/p5-0x.cpp +++ b/clang/test/CXX/expr/expr.unary/expr.sizeof/p5-0x.cpp @@ -33,6 +33,6 @@ template struct count_ints_2 { template // expected-note{{parameter pack 'Types' declared here}} struct count_types_2 { static const unsigned value = sizeof... Type; // expected-error{{missing parentheses around the size of parameter pack 'Type'}} \ - // expected-error{{Type' does not refer to the name of a parameter pack; did you mean 'Types'?}} + // expected-error{{'Type' does not refer to the name of a parameter pack; did you mean 'Types'?}} }; -- GitLab From f2bbb4cb3e211de82987b280aa98565bd3ff6ce7 Mon Sep 17 00:00:00 2001 From: Yingwei Zheng Date: Thu, 23 May 2024 01:26:48 +0800 Subject: [PATCH 162/452] [GISel][RISCV] Legalize `G_{U|S}DIVREM` (#93067) This patch expands `G_{U|S}DIVREM` into `G_{U|S}DIV + G_{U|S}REM`. `G_{U|S}DIVREM` is generated by the following fold: https://github.com/llvm/llvm-project/blob/4ea21a0261cd8599a9ffa15f5c554ab0d4bbbe27/llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp#L1410-L1471 It always folds `div + rem` pairs into `divrem` during pre-legalization. I tried to change `isLegalOrBeforeLegalizer` to `isLegal`, but it produced worse codegen on AArch64. --- .../Target/RISCV/GISel/RISCVLegalizerInfo.cpp | 3 + .../legalizer/legalize-div-rv32.mir | 90 +++++++++++++++++++ .../legalizer/legalize-div-rv64.mir | 90 +++++++++++++++++++ 3 files changed, 183 insertions(+) diff --git a/llvm/lib/Target/RISCV/GISel/RISCVLegalizerInfo.cpp b/llvm/lib/Target/RISCV/GISel/RISCVLegalizerInfo.cpp index a1d3aadb816a..c6d11b8a8bd7 100644 --- a/llvm/lib/Target/RISCV/GISel/RISCVLegalizerInfo.cpp +++ b/llvm/lib/Target/RISCV/GISel/RISCVLegalizerInfo.cpp @@ -349,6 +349,9 @@ RISCVLegalizerInfo::RISCVLegalizerInfo(const RISCVSubtarget &ST) .widenScalarToNextPow2(0); } + // TODO: Use libcall for sDoubleXLen. + getActionDefinitionsBuilder({G_UDIVREM, G_SDIVREM}).lower(); + auto &AbsActions = getActionDefinitionsBuilder(G_ABS); if (ST.hasStdExtZbb()) AbsActions.customFor({s32, sXLen}).minScalar(0, sXLen); diff --git a/llvm/test/CodeGen/RISCV/GlobalISel/legalizer/legalize-div-rv32.mir b/llvm/test/CodeGen/RISCV/GlobalISel/legalizer/legalize-div-rv32.mir index 4177a40e3826..26d8785afb47 100644 --- a/llvm/test/CodeGen/RISCV/GlobalISel/legalizer/legalize-div-rv32.mir +++ b/llvm/test/CodeGen/RISCV/GlobalISel/legalizer/legalize-div-rv32.mir @@ -555,3 +555,93 @@ body: | PseudoRET implicit $x10, implicit $x11 ... +--- +name: udivrem_i32 +body: | + bb.1.entry: + liveins: $x10, $x11 + + ; CHECK-I-LABEL: name: udivrem_i32 + ; CHECK-I: liveins: $x10, $x11 + ; CHECK-I-NEXT: {{ $}} + ; CHECK-I-NEXT: [[COPY:%[0-9]+]]:_(s32) = COPY $x10 + ; CHECK-I-NEXT: [[COPY1:%[0-9]+]]:_(s32) = COPY $x11 + ; CHECK-I-NEXT: ADJCALLSTACKDOWN 0, 0, implicit-def $x2, implicit $x2 + ; CHECK-I-NEXT: $x10 = COPY [[COPY]](s32) + ; CHECK-I-NEXT: $x11 = COPY [[COPY1]](s32) + ; CHECK-I-NEXT: PseudoCALL target-flags(riscv-call) &__udivsi3, csr_ilp32_lp64, implicit-def $x1, implicit $x10, implicit $x11, implicit-def $x10 + ; CHECK-I-NEXT: ADJCALLSTACKUP 0, 0, implicit-def $x2, implicit $x2 + ; CHECK-I-NEXT: [[COPY2:%[0-9]+]]:_(s32) = COPY $x10 + ; CHECK-I-NEXT: ADJCALLSTACKDOWN 0, 0, implicit-def $x2, implicit $x2 + ; CHECK-I-NEXT: $x10 = COPY [[COPY]](s32) + ; CHECK-I-NEXT: $x11 = COPY [[COPY1]](s32) + ; CHECK-I-NEXT: PseudoCALL target-flags(riscv-call) &__umodsi3, csr_ilp32_lp64, implicit-def $x1, implicit $x10, implicit $x11, implicit-def $x10 + ; CHECK-I-NEXT: ADJCALLSTACKUP 0, 0, implicit-def $x2, implicit $x2 + ; CHECK-I-NEXT: [[COPY3:%[0-9]+]]:_(s32) = COPY $x10 + ; CHECK-I-NEXT: [[ADD:%[0-9]+]]:_(s32) = G_ADD [[COPY2]], [[COPY3]] + ; CHECK-I-NEXT: $x10 = COPY [[ADD]](s32) + ; CHECK-I-NEXT: PseudoRET implicit $x10 + ; + ; CHECK-M-LABEL: name: udivrem_i32 + ; CHECK-M: liveins: $x10, $x11 + ; CHECK-M-NEXT: {{ $}} + ; CHECK-M-NEXT: [[COPY:%[0-9]+]]:_(s32) = COPY $x10 + ; CHECK-M-NEXT: [[COPY1:%[0-9]+]]:_(s32) = COPY $x11 + ; CHECK-M-NEXT: [[UDIV:%[0-9]+]]:_(s32) = G_UDIV [[COPY]], [[COPY1]] + ; CHECK-M-NEXT: [[UREM:%[0-9]+]]:_(s32) = G_UREM [[COPY]], [[COPY1]] + ; CHECK-M-NEXT: [[ADD:%[0-9]+]]:_(s32) = G_ADD [[UDIV]], [[UREM]] + ; CHECK-M-NEXT: $x10 = COPY [[ADD]](s32) + ; CHECK-M-NEXT: PseudoRET implicit $x10 + %0:_(s32) = COPY $x10 + %1:_(s32) = COPY $x11 + %2:_(s32), %3:_(s32) = G_UDIVREM %0, %1 + %4:_(s32) = G_ADD %2, %3 + $x10 = COPY %4(s32) + PseudoRET implicit $x10 + +... +--- +name: sdivrem_i32 +body: | + bb.1.entry: + liveins: $x10, $x11 + + ; CHECK-I-LABEL: name: sdivrem_i32 + ; CHECK-I: liveins: $x10, $x11 + ; CHECK-I-NEXT: {{ $}} + ; CHECK-I-NEXT: [[COPY:%[0-9]+]]:_(s32) = COPY $x10 + ; CHECK-I-NEXT: [[COPY1:%[0-9]+]]:_(s32) = COPY $x11 + ; CHECK-I-NEXT: ADJCALLSTACKDOWN 0, 0, implicit-def $x2, implicit $x2 + ; CHECK-I-NEXT: $x10 = COPY [[COPY]](s32) + ; CHECK-I-NEXT: $x11 = COPY [[COPY1]](s32) + ; CHECK-I-NEXT: PseudoCALL target-flags(riscv-call) &__divsi3, csr_ilp32_lp64, implicit-def $x1, implicit $x10, implicit $x11, implicit-def $x10 + ; CHECK-I-NEXT: ADJCALLSTACKUP 0, 0, implicit-def $x2, implicit $x2 + ; CHECK-I-NEXT: [[COPY2:%[0-9]+]]:_(s32) = COPY $x10 + ; CHECK-I-NEXT: ADJCALLSTACKDOWN 0, 0, implicit-def $x2, implicit $x2 + ; CHECK-I-NEXT: $x10 = COPY [[COPY]](s32) + ; CHECK-I-NEXT: $x11 = COPY [[COPY1]](s32) + ; CHECK-I-NEXT: PseudoCALL target-flags(riscv-call) &__modsi3, csr_ilp32_lp64, implicit-def $x1, implicit $x10, implicit $x11, implicit-def $x10 + ; CHECK-I-NEXT: ADJCALLSTACKUP 0, 0, implicit-def $x2, implicit $x2 + ; CHECK-I-NEXT: [[COPY3:%[0-9]+]]:_(s32) = COPY $x10 + ; CHECK-I-NEXT: [[ADD:%[0-9]+]]:_(s32) = G_ADD [[COPY2]], [[COPY3]] + ; CHECK-I-NEXT: $x10 = COPY [[ADD]](s32) + ; CHECK-I-NEXT: PseudoRET implicit $x10 + ; + ; CHECK-M-LABEL: name: sdivrem_i32 + ; CHECK-M: liveins: $x10, $x11 + ; CHECK-M-NEXT: {{ $}} + ; CHECK-M-NEXT: [[COPY:%[0-9]+]]:_(s32) = COPY $x10 + ; CHECK-M-NEXT: [[COPY1:%[0-9]+]]:_(s32) = COPY $x11 + ; CHECK-M-NEXT: [[SDIV:%[0-9]+]]:_(s32) = G_SDIV [[COPY]], [[COPY1]] + ; CHECK-M-NEXT: [[SREM:%[0-9]+]]:_(s32) = G_SREM [[COPY]], [[COPY1]] + ; CHECK-M-NEXT: [[ADD:%[0-9]+]]:_(s32) = G_ADD [[SDIV]], [[SREM]] + ; CHECK-M-NEXT: $x10 = COPY [[ADD]](s32) + ; CHECK-M-NEXT: PseudoRET implicit $x10 + %0:_(s32) = COPY $x10 + %1:_(s32) = COPY $x11 + %2:_(s32), %3:_(s32) = G_SDIVREM %0, %1 + %4:_(s32) = G_ADD %2, %3 + $x10 = COPY %4(s32) + PseudoRET implicit $x10 + +... diff --git a/llvm/test/CodeGen/RISCV/GlobalISel/legalizer/legalize-div-rv64.mir b/llvm/test/CodeGen/RISCV/GlobalISel/legalizer/legalize-div-rv64.mir index 492f9530997c..bbbe38f695d2 100644 --- a/llvm/test/CodeGen/RISCV/GlobalISel/legalizer/legalize-div-rv64.mir +++ b/llvm/test/CodeGen/RISCV/GlobalISel/legalizer/legalize-div-rv64.mir @@ -655,3 +655,93 @@ body: | PseudoRET implicit $x10, implicit $x11 ... +--- +name: udivrem_i64 +body: | + bb.1.entry: + liveins: $x10, $x11 + + ; CHECK-I-LABEL: name: udivrem_i64 + ; CHECK-I: liveins: $x10, $x11 + ; CHECK-I-NEXT: {{ $}} + ; CHECK-I-NEXT: [[COPY:%[0-9]+]]:_(s64) = COPY $x10 + ; CHECK-I-NEXT: [[COPY1:%[0-9]+]]:_(s64) = COPY $x11 + ; CHECK-I-NEXT: ADJCALLSTACKDOWN 0, 0, implicit-def $x2, implicit $x2 + ; CHECK-I-NEXT: $x10 = COPY [[COPY]](s64) + ; CHECK-I-NEXT: $x11 = COPY [[COPY1]](s64) + ; CHECK-I-NEXT: PseudoCALL target-flags(riscv-call) &__udivdi3, csr_ilp32_lp64, implicit-def $x1, implicit $x10, implicit $x11, implicit-def $x10 + ; CHECK-I-NEXT: ADJCALLSTACKUP 0, 0, implicit-def $x2, implicit $x2 + ; CHECK-I-NEXT: [[COPY2:%[0-9]+]]:_(s64) = COPY $x10 + ; CHECK-I-NEXT: ADJCALLSTACKDOWN 0, 0, implicit-def $x2, implicit $x2 + ; CHECK-I-NEXT: $x10 = COPY [[COPY]](s64) + ; CHECK-I-NEXT: $x11 = COPY [[COPY1]](s64) + ; CHECK-I-NEXT: PseudoCALL target-flags(riscv-call) &__umoddi3, csr_ilp32_lp64, implicit-def $x1, implicit $x10, implicit $x11, implicit-def $x10 + ; CHECK-I-NEXT: ADJCALLSTACKUP 0, 0, implicit-def $x2, implicit $x2 + ; CHECK-I-NEXT: [[COPY3:%[0-9]+]]:_(s64) = COPY $x10 + ; CHECK-I-NEXT: [[ADD:%[0-9]+]]:_(s64) = G_ADD [[COPY2]], [[COPY3]] + ; CHECK-I-NEXT: $x10 = COPY [[ADD]](s64) + ; CHECK-I-NEXT: PseudoRET implicit $x10 + ; + ; CHECK-M-LABEL: name: udivrem_i64 + ; CHECK-M: liveins: $x10, $x11 + ; CHECK-M-NEXT: {{ $}} + ; CHECK-M-NEXT: [[COPY:%[0-9]+]]:_(s64) = COPY $x10 + ; CHECK-M-NEXT: [[COPY1:%[0-9]+]]:_(s64) = COPY $x11 + ; CHECK-M-NEXT: [[UDIV:%[0-9]+]]:_(s64) = G_UDIV [[COPY]], [[COPY1]] + ; CHECK-M-NEXT: [[UREM:%[0-9]+]]:_(s64) = G_UREM [[COPY]], [[COPY1]] + ; CHECK-M-NEXT: [[ADD:%[0-9]+]]:_(s64) = G_ADD [[UDIV]], [[UREM]] + ; CHECK-M-NEXT: $x10 = COPY [[ADD]](s64) + ; CHECK-M-NEXT: PseudoRET implicit $x10 + %0:_(s64) = COPY $x10 + %1:_(s64) = COPY $x11 + %2:_(s64), %3:_(s64) = G_UDIVREM %0, %1 + %4:_(s64) = G_ADD %2, %3 + $x10 = COPY %4(s64) + PseudoRET implicit $x10 + +... +--- +name: sdivrem_i64 +body: | + bb.1.entry: + liveins: $x10, $x11 + + ; CHECK-I-LABEL: name: sdivrem_i64 + ; CHECK-I: liveins: $x10, $x11 + ; CHECK-I-NEXT: {{ $}} + ; CHECK-I-NEXT: [[COPY:%[0-9]+]]:_(s64) = COPY $x10 + ; CHECK-I-NEXT: [[COPY1:%[0-9]+]]:_(s64) = COPY $x11 + ; CHECK-I-NEXT: ADJCALLSTACKDOWN 0, 0, implicit-def $x2, implicit $x2 + ; CHECK-I-NEXT: $x10 = COPY [[COPY]](s64) + ; CHECK-I-NEXT: $x11 = COPY [[COPY1]](s64) + ; CHECK-I-NEXT: PseudoCALL target-flags(riscv-call) &__divdi3, csr_ilp32_lp64, implicit-def $x1, implicit $x10, implicit $x11, implicit-def $x10 + ; CHECK-I-NEXT: ADJCALLSTACKUP 0, 0, implicit-def $x2, implicit $x2 + ; CHECK-I-NEXT: [[COPY2:%[0-9]+]]:_(s64) = COPY $x10 + ; CHECK-I-NEXT: ADJCALLSTACKDOWN 0, 0, implicit-def $x2, implicit $x2 + ; CHECK-I-NEXT: $x10 = COPY [[COPY]](s64) + ; CHECK-I-NEXT: $x11 = COPY [[COPY1]](s64) + ; CHECK-I-NEXT: PseudoCALL target-flags(riscv-call) &__moddi3, csr_ilp32_lp64, implicit-def $x1, implicit $x10, implicit $x11, implicit-def $x10 + ; CHECK-I-NEXT: ADJCALLSTACKUP 0, 0, implicit-def $x2, implicit $x2 + ; CHECK-I-NEXT: [[COPY3:%[0-9]+]]:_(s64) = COPY $x10 + ; CHECK-I-NEXT: [[ADD:%[0-9]+]]:_(s64) = G_ADD [[COPY2]], [[COPY3]] + ; CHECK-I-NEXT: $x10 = COPY [[ADD]](s64) + ; CHECK-I-NEXT: PseudoRET implicit $x10 + ; + ; CHECK-M-LABEL: name: sdivrem_i64 + ; CHECK-M: liveins: $x10, $x11 + ; CHECK-M-NEXT: {{ $}} + ; CHECK-M-NEXT: [[COPY:%[0-9]+]]:_(s64) = COPY $x10 + ; CHECK-M-NEXT: [[COPY1:%[0-9]+]]:_(s64) = COPY $x11 + ; CHECK-M-NEXT: [[SDIV:%[0-9]+]]:_(s64) = G_SDIV [[COPY]], [[COPY1]] + ; CHECK-M-NEXT: [[SREM:%[0-9]+]]:_(s64) = G_SREM [[COPY]], [[COPY1]] + ; CHECK-M-NEXT: [[ADD:%[0-9]+]]:_(s64) = G_ADD [[SDIV]], [[SREM]] + ; CHECK-M-NEXT: $x10 = COPY [[ADD]](s64) + ; CHECK-M-NEXT: PseudoRET implicit $x10 + %0:_(s64) = COPY $x10 + %1:_(s64) = COPY $x11 + %2:_(s64), %3:_(s64) = G_SDIVREM %0, %1 + %4:_(s64) = G_ADD %2, %3 + $x10 = COPY %4(s64) + PseudoRET implicit $x10 + +... -- GitLab From e558d21e87882d40e29d858b1269ee8f1ddf2a38 Mon Sep 17 00:00:00 2001 From: Kevin Frei Date: Wed, 22 May 2024 13:31:04 -0400 Subject: [PATCH 163/452] [lldb] Added Debuginfod tests and fixed a couple issues (#92572) Here we go with attempt number five. Again, no changes to the LLDB code diff, which has been reviewed several times. For the tests, I added a `@skipIfCurlSupportMissing` annotation so that the Debuginfod mocked server stuff won't run, and I also disabled non-Linux/FreeBSD hosts altogether, as they fail for platform reasons on macOS and Windows. In addition, I updated the process for extracting the GNU BuildID to no create a target, per some feedback on the previous diff. For reference, previous PR's (landed, backed out after the fact for various reasons) #90622, #87676, #86812, #85693 --------- Co-authored-by: Kevin Frei --- lldb/include/lldb/Host/Config.h.cmake | 2 + .../Python/lldbsuite/test/decorators.py | 4 + .../Python/lldbsuite/test/make/Makefile.rules | 26 ++- lldb/source/API/SBDebugger.cpp | 13 +- .../SymbolFile/DWARF/SymbolFileDWARF.cpp | 38 ++-- .../Plugins/SymbolLocator/CMakeLists.txt | 7 +- .../SymbolVendor/ELF/SymbolVendorELF.cpp | 29 ++- lldb/test/API/debuginfod/Normal/Makefile | 19 ++ .../API/debuginfod/Normal/TestDebuginfod.py | 186 +++++++++++++++++ lldb/test/API/debuginfod/Normal/main.c | 7 + lldb/test/API/debuginfod/SplitDWARF/Makefile | 23 ++ .../SplitDWARF/TestDebuginfodDWP.py | 196 ++++++++++++++++++ lldb/test/API/debuginfod/SplitDWARF/main.c | 7 + 13 files changed, 535 insertions(+), 22 deletions(-) create mode 100644 lldb/test/API/debuginfod/Normal/Makefile create mode 100644 lldb/test/API/debuginfod/Normal/TestDebuginfod.py create mode 100644 lldb/test/API/debuginfod/Normal/main.c create mode 100644 lldb/test/API/debuginfod/SplitDWARF/Makefile create mode 100644 lldb/test/API/debuginfod/SplitDWARF/TestDebuginfodDWP.py create mode 100644 lldb/test/API/debuginfod/SplitDWARF/main.c diff --git a/lldb/include/lldb/Host/Config.h.cmake b/lldb/include/lldb/Host/Config.h.cmake index 3defa454f6d4..9e538534086a 100644 --- a/lldb/include/lldb/Host/Config.h.cmake +++ b/lldb/include/lldb/Host/Config.h.cmake @@ -33,6 +33,8 @@ #cmakedefine01 LLDB_ENABLE_LZMA +#cmakedefine01 LLVM_ENABLE_CURL + #cmakedefine01 LLDB_ENABLE_CURSES #cmakedefine01 CURSES_HAVE_NCURSES_CURSES_H diff --git a/lldb/packages/Python/lldbsuite/test/decorators.py b/lldb/packages/Python/lldbsuite/test/decorators.py index 79cc0a2aeacb..b4ac3bdabac8 100644 --- a/lldb/packages/Python/lldbsuite/test/decorators.py +++ b/lldb/packages/Python/lldbsuite/test/decorators.py @@ -1055,6 +1055,10 @@ def _get_bool_config_skip_if_decorator(key): return unittest.skipIf(not have, "requires " + key) +def skipIfCurlSupportMissing(func): + return _get_bool_config_skip_if_decorator("curl")(func) + + def skipIfCursesSupportMissing(func): return _get_bool_config_skip_if_decorator("curses")(func) diff --git a/lldb/packages/Python/lldbsuite/test/make/Makefile.rules b/lldb/packages/Python/lldbsuite/test/make/Makefile.rules index bd8eea3d6f5a..2cbc918ebbae 100644 --- a/lldb/packages/Python/lldbsuite/test/make/Makefile.rules +++ b/lldb/packages/Python/lldbsuite/test/make/Makefile.rules @@ -51,7 +51,7 @@ LLDB_BASE_DIR := $(THIS_FILE_DIR)/../../../../../ # # GNUWin32 uname gives "windows32" or "server version windows32" while # some versions of MSYS uname return "MSYS_NT*", but most environments -# standardize on "Windows_NT", so we'll make it consistent here. +# standardize on "Windows_NT", so we'll make it consistent here. # When running tests from Visual Studio, the environment variable isn't # inherited all the way down to the process spawned for make. #---------------------------------------------------------------------- @@ -210,6 +210,12 @@ else ifeq "$(SPLIT_DEBUG_SYMBOLS)" "YES" DSYM = $(EXE).debug endif + + ifeq "$(MAKE_DWP)" "YES" + MAKE_DWO := YES + DWP_NAME = $(EXE).dwp + DYLIB_DWP_NAME = $(DYLIB_NAME).dwp + endif endif LIMIT_DEBUG_INFO_FLAGS = @@ -358,6 +364,7 @@ ifneq "$(OS)" "Darwin" OBJCOPY ?= $(call replace_cc_with,objcopy) ARCHIVER ?= $(call replace_cc_with,ar) + DWP ?= $(call replace_cc_with,dwp) override AR = $(ARCHIVER) endif @@ -528,6 +535,10 @@ ifneq "$(CXX)" "" endif endif +ifeq "$(GEN_GNU_BUILD_ID)" "YES" + LDFLAGS += -Wl,--build-id +endif + #---------------------------------------------------------------------- # DYLIB_ONLY variable can be used to skip the building of a.out. # See the sections below regarding dSYM file as well as the building of @@ -566,10 +577,17 @@ else endif else ifeq "$(SPLIT_DEBUG_SYMBOLS)" "YES" +ifeq "$(SAVE_FULL_DEBUG_BINARY)" "YES" + cp "$(EXE)" "$(EXE).unstripped" +endif $(OBJCOPY) --only-keep-debug "$(EXE)" "$(DSYM)" $(OBJCOPY) --strip-debug --add-gnu-debuglink="$(DSYM)" "$(EXE)" "$(EXE)" endif +ifeq "$(MAKE_DWP)" "YES" + $(DWP) -o "$(DWP_NAME)" $(DWOS) endif +endif + #---------------------------------------------------------------------- # Make the dylib @@ -611,9 +629,15 @@ endif else $(LD) $(DYLIB_OBJECTS) $(LDFLAGS) -shared -o "$(DYLIB_FILENAME)" ifeq "$(SPLIT_DEBUG_SYMBOLS)" "YES" + ifeq "$(SAVE_FULL_DEBUG_BINARY)" "YES" + cp "$(DYLIB_FILENAME)" "$(DYLIB_FILENAME).unstripped" + endif $(OBJCOPY) --only-keep-debug "$(DYLIB_FILENAME)" "$(DYLIB_FILENAME).debug" $(OBJCOPY) --strip-debug --add-gnu-debuglink="$(DYLIB_FILENAME).debug" "$(DYLIB_FILENAME)" "$(DYLIB_FILENAME)" endif +ifeq "$(MAKE_DWP)" "YES" + $(DWP) -o $(DYLIB_DWP_FILE) $(DYLIB_DWOS) +endif endif #---------------------------------------------------------------------- diff --git a/lldb/source/API/SBDebugger.cpp b/lldb/source/API/SBDebugger.cpp index 7ef0d6efd4aa..6e19a6861f37 100644 --- a/lldb/source/API/SBDebugger.cpp +++ b/lldb/source/API/SBDebugger.cpp @@ -775,6 +775,9 @@ SBStructuredData SBDebugger::GetBuildConfiguration() { AddBoolConfigEntry( *config_up, "xml", XMLDocument::XMLEnabled(), "A boolean value that indicates if XML support is enabled in LLDB"); + AddBoolConfigEntry( + *config_up, "curl", LLVM_ENABLE_CURL, + "A boolean value that indicates if CURL support is enabled in LLDB"); AddBoolConfigEntry( *config_up, "curses", LLDB_ENABLE_CURSES, "A boolean value that indicates if curses support is enabled in LLDB"); @@ -1724,20 +1727,20 @@ SBDebugger::LoadTraceFromFile(SBError &error, void SBDebugger::RequestInterrupt() { LLDB_INSTRUMENT_VA(this); - + if (m_opaque_sp) - m_opaque_sp->RequestInterrupt(); + m_opaque_sp->RequestInterrupt(); } void SBDebugger::CancelInterruptRequest() { LLDB_INSTRUMENT_VA(this); - + if (m_opaque_sp) - m_opaque_sp->CancelInterruptRequest(); + m_opaque_sp->CancelInterruptRequest(); } bool SBDebugger::InterruptRequested() { LLDB_INSTRUMENT_VA(this); - + if (m_opaque_sp) return m_opaque_sp->InterruptRequested(); return false; diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp index f6f152726bf7..df9704ef6186 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp @@ -4381,26 +4381,38 @@ const std::shared_ptr &SymbolFileDWARF::GetDwpSymbolFile() { FileSpecList search_paths = Target::GetDefaultDebugFileSearchPaths(); ModuleSpec module_spec; module_spec.GetFileSpec() = m_objfile_sp->GetFileSpec(); + FileSpec dwp_filespec; for (const auto &symfile : symfiles.files()) { module_spec.GetSymbolFileSpec() = FileSpec(symfile.GetPath() + ".dwp", symfile.GetPathStyle()); LLDB_LOG(log, "Searching for DWP using: \"{0}\"", module_spec.GetSymbolFileSpec()); - FileSpec dwp_filespec = + dwp_filespec = PluginManager::LocateExecutableSymbolFile(module_spec, search_paths); if (FileSystem::Instance().Exists(dwp_filespec)) { - LLDB_LOG(log, "Found DWP file: \"{0}\"", dwp_filespec); - DataBufferSP dwp_file_data_sp; - lldb::offset_t dwp_file_data_offset = 0; - ObjectFileSP dwp_obj_file = ObjectFile::FindPlugin( - GetObjectFile()->GetModule(), &dwp_filespec, 0, - FileSystem::Instance().GetByteSize(dwp_filespec), dwp_file_data_sp, - dwp_file_data_offset); - if (dwp_obj_file) { - m_dwp_symfile = std::make_shared( - *this, dwp_obj_file, DIERef::k_file_index_mask); - break; - } + break; + } + } + if (!FileSystem::Instance().Exists(dwp_filespec)) { + LLDB_LOG(log, "No DWP file found locally"); + // Fill in the UUID for the module we're trying to match for, so we can + // find the correct DWP file, as the Debuginfod plugin uses *only* this + // data to correctly match the DWP file with the binary. + module_spec.GetUUID() = m_objfile_sp->GetUUID(); + dwp_filespec = + PluginManager::LocateExecutableSymbolFile(module_spec, search_paths); + } + if (FileSystem::Instance().Exists(dwp_filespec)) { + LLDB_LOG(log, "Found DWP file: \"{0}\"", dwp_filespec); + DataBufferSP dwp_file_data_sp; + lldb::offset_t dwp_file_data_offset = 0; + ObjectFileSP dwp_obj_file = ObjectFile::FindPlugin( + GetObjectFile()->GetModule(), &dwp_filespec, 0, + FileSystem::Instance().GetByteSize(dwp_filespec), dwp_file_data_sp, + dwp_file_data_offset); + if (dwp_obj_file) { + m_dwp_symfile = std::make_shared( + *this, dwp_obj_file, DIERef::k_file_index_mask); } } if (!m_dwp_symfile) { diff --git a/lldb/source/Plugins/SymbolLocator/CMakeLists.txt b/lldb/source/Plugins/SymbolLocator/CMakeLists.txt index ca969626f4ff..3367022639ab 100644 --- a/lldb/source/Plugins/SymbolLocator/CMakeLists.txt +++ b/lldb/source/Plugins/SymbolLocator/CMakeLists.txt @@ -1,5 +1,10 @@ +# Order matters here: the first symbol locator prevents further searching. +# For DWARF binaries that are both stripped and split, the Default plugin +# will return the stripped binary when asked for the ObjectFile, which then +# prevents an unstripped binary from being requested from the Debuginfod +# provider. +add_subdirectory(Debuginfod) add_subdirectory(Default) if (CMAKE_SYSTEM_NAME MATCHES "Darwin") add_subdirectory(DebugSymbols) endif() -add_subdirectory(Debuginfod) diff --git a/lldb/source/Plugins/SymbolVendor/ELF/SymbolVendorELF.cpp b/lldb/source/Plugins/SymbolVendor/ELF/SymbolVendorELF.cpp index b5fe35d71032..f296e655cc46 100644 --- a/lldb/source/Plugins/SymbolVendor/ELF/SymbolVendorELF.cpp +++ b/lldb/source/Plugins/SymbolVendor/ELF/SymbolVendorELF.cpp @@ -44,6 +44,24 @@ llvm::StringRef SymbolVendorELF::GetPluginDescriptionStatic() { "executables."; } +// If this is needed elsewhere, it can be exported/moved. +static bool IsDwpSymbolFile(const lldb::ModuleSP &module_sp, + const FileSpec &file_spec) { + DataBufferSP dwp_file_data_sp; + lldb::offset_t dwp_file_data_offset = 0; + // Try to create an ObjectFile from the file_spec. + ObjectFileSP dwp_obj_file = ObjectFile::FindPlugin( + module_sp, &file_spec, 0, FileSystem::Instance().GetByteSize(file_spec), + dwp_file_data_sp, dwp_file_data_offset); + // The presence of a debug_cu_index section is the key identifying feature of + // a DWP file. Make sure we don't fill in the section list on dwp_obj_file + // (by calling GetSectionList(false)) as this function could be called before + // we may have all the symbol files collected and available. + return dwp_obj_file && ObjectFileELF::classof(dwp_obj_file.get()) && + dwp_obj_file->GetSectionList(false)->FindSectionByType( + eSectionTypeDWARFDebugCuIndex, false); +} + // CreateInstance // // Platforms can register a callback to use when creating symbol vendors to @@ -87,8 +105,15 @@ SymbolVendorELF::CreateInstance(const lldb::ModuleSP &module_sp, FileSpecList search_paths = Target::GetDefaultDebugFileSearchPaths(); FileSpec dsym_fspec = PluginManager::LocateExecutableSymbolFile(module_spec, search_paths); - if (!dsym_fspec) - return nullptr; + if (!dsym_fspec || IsDwpSymbolFile(module_sp, dsym_fspec)) { + // If we have a stripped binary or if we got a DWP file, we should prefer + // symbols in the executable acquired through a plugin. + ModuleSpec unstripped_spec = + PluginManager::LocateExecutableObjectFile(module_spec); + if (!unstripped_spec) + return nullptr; + dsym_fspec = unstripped_spec.GetFileSpec(); + } DataBufferSP dsym_file_data_sp; lldb::offset_t dsym_file_data_offset = 0; diff --git a/lldb/test/API/debuginfod/Normal/Makefile b/lldb/test/API/debuginfod/Normal/Makefile new file mode 100644 index 000000000000..54bd7adae241 --- /dev/null +++ b/lldb/test/API/debuginfod/Normal/Makefile @@ -0,0 +1,19 @@ +C_SOURCES := main.c + +# For normal (non DWP) Debuginfod tests, we need: + +# * The full binary: a.out.unstripped +# Produced by Makefile.rules with SAVE_FULL_DEBUG_BINARY set to YES and +# SPLIT_DEBUG_SYMBOLS set to YES + +# * The stripped binary (a.out) +# Produced by Makefile.rules with SPLIT_DEBUG_SYMBOLS set to YES + +# * The 'only-keep-debug' binary (a.out.debug) +# Produced below + +SPLIT_DEBUG_SYMBOLS := YES +SAVE_FULL_DEBUG_BINARY := YES +GEN_GNU_BUILD_ID := YES + +include Makefile.rules diff --git a/lldb/test/API/debuginfod/Normal/TestDebuginfod.py b/lldb/test/API/debuginfod/Normal/TestDebuginfod.py new file mode 100644 index 000000000000..1860c56ef3e9 --- /dev/null +++ b/lldb/test/API/debuginfod/Normal/TestDebuginfod.py @@ -0,0 +1,186 @@ +import os +import shutil +import tempfile + +import lldb +from lldbsuite.test.decorators import * +import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test.lldbtest import * + + +""" +Test support for the DebugInfoD network symbol acquisition protocol. +This one is for simple / no split-dwarf scenarios. + +For no-split-dwarf scenarios, there are 2 variations: +1 - A stripped binary with it's corresponding unstripped binary: +2 - A stripped binary with a corresponding --only-keep-debug symbols file +""" + + +class DebugInfodTests(TestBase): + # No need to try every flavor of debug inf. + NO_DEBUG_INFO_TESTCASE = True + + @skipUnlessPlatform(["linux", "freebsd"]) + def test_normal_no_symbols(self): + """ + Validate behavior with no symbols or symbol locator. + ('baseline negative' behavior) + """ + test_root = self.config_test(["a.out"]) + self.try_breakpoint(False) + + @skipUnlessPlatform(["linux", "freebsd"]) + def test_normal_default(self): + """ + Validate behavior with symbols, but no symbol locator. + ('baseline positive' behavior) + """ + test_root = self.config_test(["a.out", "a.out.debug"]) + self.try_breakpoint(True) + + @skipIfCurlSupportMissing + @skipUnlessPlatform(["linux", "freebsd"]) + def test_debuginfod_symbols(self): + """ + Test behavior with the full binary available from Debuginfod as + 'debuginfo' from the plug-in. + """ + test_root = self.config_test(["a.out"], "a.out.unstripped") + self.try_breakpoint(True) + + @skipIfCurlSupportMissing + @skipUnlessPlatform(["linux", "freebsd"]) + def test_debuginfod_executable(self): + """ + Test behavior with the full binary available from Debuginfod as + 'executable' from the plug-in. + """ + test_root = self.config_test(["a.out"], None, "a.out.unstripped") + self.try_breakpoint(True) + + @skipIfCurlSupportMissing + @skipUnlessPlatform(["linux", "freebsd"]) + def test_debuginfod_okd_symbols(self): + """ + Test behavior with the 'only-keep-debug' symbols available from Debuginfod. + """ + test_root = self.config_test(["a.out"], "a.out.debug") + self.try_breakpoint(True) + + def try_breakpoint(self, should_have_loc): + """ + This function creates a target from self.aout, sets a function-name + breakpoint, and checks to see if we have a file/line location, + as a way to validate that the symbols have been loaded. + should_have_loc specifies if we're testing that symbols have or + haven't been loaded. + """ + target = self.dbg.CreateTarget(self.aout) + self.assertTrue(target and target.IsValid(), "Target is valid") + + bp = target.BreakpointCreateByName("func") + self.assertTrue(bp and bp.IsValid(), "Breakpoint is valid") + self.assertEqual(bp.GetNumLocations(), 1) + + loc = bp.GetLocationAtIndex(0) + self.assertTrue(loc and loc.IsValid(), "Location is valid") + addr = loc.GetAddress() + self.assertTrue(addr and addr.IsValid(), "Loc address is valid") + line_entry = addr.GetLineEntry() + self.assertEqual( + should_have_loc, + line_entry != None and line_entry.IsValid(), + "Loc line entry is valid", + ) + if should_have_loc: + self.assertEqual(line_entry.GetLine(), 4) + self.assertEqual( + line_entry.GetFileSpec().GetFilename(), + self.main_source_file.GetFilename(), + ) + self.dbg.DeleteTarget(target) + shutil.rmtree(self.tmp_dir) + + def config_test(self, local_files, debuginfo=None, executable=None): + """ + Set up a test with local_files[] copied to a different location + so that we control which files are, or are not, found in the file system. + Also, create a stand-alone file-system 'hosted' debuginfod server with the + provided debuginfo and executable files (if they exist) + + Make the filesystem look like: + + /tmp//test/[local_files] + + /tmp//cache (for lldb to use as a temp cache) + + /tmp//buildid//executable -> + /tmp//buildid//debuginfo -> + Returns the /tmp/ path + """ + + self.build() + + uuid = self.getUUID("a.out") + if not uuid: + self.fail("Could not get UUID for a.out") + return + self.main_source_file = lldb.SBFileSpec("main.c") + self.tmp_dir = tempfile.mkdtemp() + test_dir = os.path.join(self.tmp_dir, "test") + os.makedirs(test_dir) + + self.aout = "" + # Copy the files used by the test: + for f in local_files: + shutil.copy(self.getBuildArtifact(f), test_dir) + # The first item is the binary to be used for the test + if self.aout == "": + self.aout = os.path.join(test_dir, f) + + use_debuginfod = debuginfo != None or executable != None + + # Populated the 'file://... mocked' Debuginfod server: + if use_debuginfod: + os.makedirs(os.path.join(self.tmp_dir, "cache")) + uuid_dir = os.path.join(self.tmp_dir, "buildid", uuid) + os.makedirs(uuid_dir) + if debuginfo: + shutil.copy( + self.getBuildArtifact(debuginfo), + os.path.join(uuid_dir, "debuginfo"), + ) + if executable: + shutil.copy( + self.getBuildArtifact(executable), + os.path.join(uuid_dir, "executable"), + ) + + # Configure LLDB for the test: + self.runCmd( + "settings set symbols.enable-external-lookup %s" + % str(use_debuginfod).lower() + ) + self.runCmd("settings clear plugin.symbol-locator.debuginfod.server-urls") + if use_debuginfod: + self.runCmd( + "settings set plugin.symbol-locator.debuginfod.cache-path %s/cache" + % self.tmp_dir + ) + self.runCmd( + "settings insert-before plugin.symbol-locator.debuginfod.server-urls 0 file://%s" + % self.tmp_dir + ) + + def getUUID(self, filename): + try: + spec = lldb.SBModuleSpec() + spec.SetFileSpec(lldb.SBFileSpec(self.getBuildArtifact(filename))) + module = lldb.SBModule(spec) + uuid = module.GetUUIDString().replace("-", "").lower() + # Don't want lldb's fake 32 bit CRC's for this one + return uuid if len(uuid) > 8 else None + except: + return None diff --git a/lldb/test/API/debuginfod/Normal/main.c b/lldb/test/API/debuginfod/Normal/main.c new file mode 100644 index 000000000000..4c7184609b45 --- /dev/null +++ b/lldb/test/API/debuginfod/Normal/main.c @@ -0,0 +1,7 @@ +// This is a dump little pair of test files + +int func(int argc, const char *argv[]) { + return (argc + 1) * (argv[argc][0] + 2); +} + +int main(int argc, const char *argv[]) { return func(0, argv); } diff --git a/lldb/test/API/debuginfod/SplitDWARF/Makefile b/lldb/test/API/debuginfod/SplitDWARF/Makefile new file mode 100644 index 000000000000..3ab9a969e5a4 --- /dev/null +++ b/lldb/test/API/debuginfod/SplitDWARF/Makefile @@ -0,0 +1,23 @@ +C_SOURCES := main.c + +# For split-dwarf Debuginfod tests, we need: + +# * A .DWP file (a.out.dwp) +# Produced by Makefile.rules with MAKE_DWP set to YES + +# * The "full" binary (missing things that live in .dwo's) (a.out.unstripped) +# Produced by Makefile.rules with SAVE_FULL_DEBUG_BINARY set to YES and +# SPLIT_DEBUG_SYMBOLS set to YES + +# * The stripped binary (a.out) +# Produced by Makefile.rules + +# * The 'only-keep-debug' binary (a.out.debug) +# Produced below + +MAKE_DWP := YES +SPLIT_DEBUG_SYMBOLS := YES +SAVE_FULL_DEBUG_BINARY := YES +GEN_GNU_BUILD_ID := YES + +include Makefile.rules diff --git a/lldb/test/API/debuginfod/SplitDWARF/TestDebuginfodDWP.py b/lldb/test/API/debuginfod/SplitDWARF/TestDebuginfodDWP.py new file mode 100644 index 000000000000..f7d91c45b0af --- /dev/null +++ b/lldb/test/API/debuginfod/SplitDWARF/TestDebuginfodDWP.py @@ -0,0 +1,196 @@ +""" +Test support for the DebugInfoD network symbol acquisition protocol. +""" +import os +import shutil +import tempfile + +import lldb +from lldbsuite.test.decorators import * +import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test.lldbtest import * + + +""" +Test support for the DebugInfoD network symbol acquisition protocol. +This file is for split-dwarf (dwp) scenarios. + +1 - A split binary target with it's corresponding DWP file +2 - A stripped, split binary target with an unstripped binary and a DWP file +3 - A stripped, split binary target with an --only-keep-debug symbols file and a DWP file +""" + + +class DebugInfodDWPTests(TestBase): + # No need to try every flavor of debug inf. + NO_DEBUG_INFO_TESTCASE = True + + @skipUnlessPlatform(["linux", "freebsd"]) + def test_normal_stripped(self): + """ + Validate behavior with a stripped binary, no symbols or symbol locator. + """ + self.config_test(["a.out"]) + self.try_breakpoint(False) + + @skipUnlessPlatform(["linux", "freebsd"]) + def test_normal_stripped_split_with_dwp(self): + """ + Validate behavior with symbols, but no symbol locator. + """ + self.config_test(["a.out", "a.out.debug", "a.out.dwp"]) + self.try_breakpoint(True) + + @skipUnlessPlatform(["linux", "freebsd"]) + def test_normal_stripped_only_dwp(self): + """ + Validate behavior *with* dwp symbols only, but missing other symbols, + but no symbol locator. This shouldn't work: without the other symbols + DWO's appear mostly useless. + """ + self.config_test(["a.out", "a.out.dwp"]) + self.try_breakpoint(False) + + @skipIfCurlSupportMissing + @skipUnlessPlatform(["linux", "freebsd"]) + def test_debuginfod_dwp_from_service(self): + """ + Test behavior with the unstripped binary, and DWP from the service. + """ + self.config_test(["a.out.debug"], "a.out.dwp") + self.try_breakpoint(True) + + @skipIfCurlSupportMissing + @skipUnlessPlatform(["linux", "freebsd"]) + def test_debuginfod_both_symfiles_from_service(self): + """ + Test behavior with a stripped binary, with the unstripped binary and + dwp symbols from Debuginfod. + """ + self.config_test(["a.out"], "a.out.dwp", "a.out.unstripped") + self.try_breakpoint(True) + + @skipIfCurlSupportMissing + @skipUnlessPlatform(["linux", "freebsd"]) + def test_debuginfod_both_okd_symfiles_from_service(self): + """ + Test behavior with both the only-keep-debug symbols and the dwp symbols + from Debuginfod. + """ + self.config_test(["a.out"], "a.out.dwp", "a.out.debug") + self.try_breakpoint(True) + + def try_breakpoint(self, should_have_loc): + """ + This function creates a target from self.aout, sets a function-name + breakpoint, and checks to see if we have a file/line location, + as a way to validate that the symbols have been loaded. + should_have_loc specifies if we're testing that symbols have or + haven't been loaded. + """ + target = self.dbg.CreateTarget(self.aout) + self.assertTrue(target and target.IsValid(), "Target is valid") + + bp = target.BreakpointCreateByName("func") + self.assertTrue(bp and bp.IsValid(), "Breakpoint is valid") + self.assertEqual(bp.GetNumLocations(), 1) + + loc = bp.GetLocationAtIndex(0) + self.assertTrue(loc and loc.IsValid(), "Location is valid") + addr = loc.GetAddress() + self.assertTrue(addr and addr.IsValid(), "Loc address is valid") + line_entry = addr.GetLineEntry() + self.assertEqual( + should_have_loc, + line_entry != None and line_entry.IsValid(), + "Loc line entry is valid", + ) + if should_have_loc: + self.assertEqual(line_entry.GetLine(), 4) + self.assertEqual( + line_entry.GetFileSpec().GetFilename(), + self.main_source_file.GetFilename(), + ) + self.dbg.DeleteTarget(target) + shutil.rmtree(self.tmp_dir) + + def config_test(self, local_files, debuginfo=None, executable=None): + """ + Set up a test with local_files[] copied to a different location + so that we control which files are, or are not, found in the file system. + Also, create a stand-alone file-system 'hosted' debuginfod server with the + provided debuginfo and executable files (if they exist) + + Make the filesystem look like: + + /tmp//test/[local_files] + + /tmp//cache (for lldb to use as a temp cache) + + /tmp//buildid//executable -> + /tmp//buildid//debuginfo -> + Returns the /tmp/ path + """ + + self.build() + + uuid = self.getUUID("a.out") + if not uuid: + self.fail("Could not get UUID for a.out") + return + self.main_source_file = lldb.SBFileSpec("main.c") + self.tmp_dir = tempfile.mkdtemp() + self.test_dir = os.path.join(self.tmp_dir, "test") + os.makedirs(self.test_dir) + + self.aout = "" + # Copy the files used by the test: + for f in local_files: + shutil.copy(self.getBuildArtifact(f), self.test_dir) + if self.aout == "": + self.aout = os.path.join(self.test_dir, f) + + use_debuginfod = debuginfo != None or executable != None + + # Populated the 'file://... mocked' Debuginfod server: + if use_debuginfod: + os.makedirs(os.path.join(self.tmp_dir, "cache")) + uuid_dir = os.path.join(self.tmp_dir, "buildid", uuid) + os.makedirs(uuid_dir) + if debuginfo: + shutil.copy( + self.getBuildArtifact(debuginfo), + os.path.join(uuid_dir, "debuginfo"), + ) + if executable: + shutil.copy( + self.getBuildArtifact(executable), + os.path.join(uuid_dir, "executable"), + ) + os.remove(self.getBuildArtifact("main.dwo")) + # Configure LLDB for the test: + self.runCmd( + "settings set symbols.enable-external-lookup %s" + % str(use_debuginfod).lower() + ) + self.runCmd("settings clear plugin.symbol-locator.debuginfod.server-urls") + if use_debuginfod: + self.runCmd( + "settings set plugin.symbol-locator.debuginfod.cache-path %s/cache" + % self.tmp_dir + ) + self.runCmd( + "settings insert-before plugin.symbol-locator.debuginfod.server-urls 0 file://%s" + % self.tmp_dir + ) + + def getUUID(self, filename): + try: + spec = lldb.SBModuleSpec() + spec.SetFileSpec(lldb.SBFileSpec(self.getBuildArtifact(filename))) + module = lldb.SBModule(spec) + uuid = module.GetUUIDString().replace("-", "").lower() + # Don't want lldb's fake 32 bit CRC's for this one + return uuid if len(uuid) > 8 else None + except: + return None diff --git a/lldb/test/API/debuginfod/SplitDWARF/main.c b/lldb/test/API/debuginfod/SplitDWARF/main.c new file mode 100644 index 000000000000..4c7184609b45 --- /dev/null +++ b/lldb/test/API/debuginfod/SplitDWARF/main.c @@ -0,0 +1,7 @@ +// This is a dump little pair of test files + +int func(int argc, const char *argv[]) { + return (argc + 1) * (argv[argc][0] + 2); +} + +int main(int argc, const char *argv[]) { return func(0, argv); } -- GitLab From dfc6a1936731b545ad0880a9c52bd043e4c4309d Mon Sep 17 00:00:00 2001 From: Aaron Ballman Date: Wed, 22 May 2024 13:34:26 -0400 Subject: [PATCH 164/452] Reword OpenMP diagnostics for style; NFC Three different OpenMP diagnostics were starting with a capital letter, so this makes them all lowercase and updates the tests accordingly. --- .../clang/Basic/DiagnosticSemaKinds.td | 6 ++-- .../distribute_firstprivate_messages.cpp | 6 ++-- ...ute_parallel_for_firstprivate_messages.cpp | 18 +++++------ ...bute_parallel_for_lastprivate_messages.cpp | 18 +++++------ ...stribute_parallel_for_private_messages.cpp | 2 +- ...ribute_parallel_for_reduction_messages.cpp | 20 ++++++------- ...ute_parallel_for_simd_private_messages.cpp | 2 +- ...bute_parallel_for_simd_shared_messages.cpp | 16 +++++----- .../distribute_simd_firstprivate_messages.cpp | 18 +++++------ .../distribute_simd_lastprivate_messages.cpp | 18 +++++------ .../OpenMP/distribute_simd_loop_messages.cpp | 30 +++++++++---------- .../distribute_simd_private_messages.cpp | 2 +- .../distribute_simd_reduction_messages.cpp | 20 ++++++------- clang/test/OpenMP/reduction_implicit_map.cpp | 2 +- ...ires_default_atomic_mem_order_messages.cpp | 4 +-- clang/test/OpenMP/requires_messages.cpp | 26 ++++++++-------- .../target_device_ancestor_messages.cpp | 2 +- .../OpenMP/target_firstprivate_messages.cpp | 2 +- clang/test/OpenMP/target_map_messages.cpp | 20 ++++++------- .../target_parallel_for_private_messages.cpp | 2 +- ...get_parallel_for_simd_private_messages.cpp | 2 +- clang/test/OpenMP/target_private_messages.cpp | 2 +- .../OpenMP/target_simd_private_messages.cpp | 2 +- ...teams_distribute_firstprivate_messages.cpp | 2 +- .../OpenMP/teams_distribute_loop_messages.cpp | 28 ++++++++--------- ..._distribute_parallel_for_loop_messages.cpp | 28 ++++++++--------- ...ribute_parallel_for_simd_loop_messages.cpp | 28 ++++++++--------- .../teams_distribute_simd_loop_messages.cpp | 28 ++++++++--------- 28 files changed, 177 insertions(+), 177 deletions(-) diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index 41a9745ddb57..34531411f1c0 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -11335,10 +11335,10 @@ def err_omp_reduction_vla_unsupported : Error< def err_omp_linear_distribute_var_non_loop_iteration : Error< "only loop iteration variables are allowed in 'linear' clause in distribute directives">; def warn_omp_non_trivial_type_mapped : Warning< - "Type %0 is not trivially copyable and not guaranteed to be mapped correctly">, + "type %0 is not trivially copyable and not guaranteed to be mapped correctly">, InGroup; def err_omp_requires_clause_redeclaration : Error < - "Only one %0 clause can appear on a requires directive in a single translation unit">; + "only one %0 clause can appear on a requires directive in a single translation unit">; def note_omp_requires_previous_clause : Note < "%0 clause previously used here">; def err_omp_directive_before_requires : Error < @@ -11346,7 +11346,7 @@ def err_omp_directive_before_requires : Error < def note_omp_requires_encountered_directive : Note < "'%0' previously encountered here">; def err_omp_device_ancestor_without_requires_reverse_offload : Error < - "Device clause with ancestor device-modifier used without specifying 'requires reverse_offload'">; + "device clause with ancestor device-modifier used without specifying 'requires reverse_offload'">; def err_omp_invalid_scope : Error < "'#pragma omp %0' directive must appear only in file scope">; def note_omp_invalid_length_on_this_ptr_mapping : Note < diff --git a/clang/test/OpenMP/distribute_firstprivate_messages.cpp b/clang/test/OpenMP/distribute_firstprivate_messages.cpp index 30fa8be519ef..f507c86b601f 100644 --- a/clang/test/OpenMP/distribute_firstprivate_messages.cpp +++ b/clang/test/OpenMP/distribute_firstprivate_messages.cpp @@ -95,7 +95,7 @@ int main(int argc, char **argv) { for (i = 0; i < argc; ++i) foo(); #pragma omp target #pragma omp teams - #pragma omp distribute firstprivate (a, b, c, d, f) // expected-error {{firstprivate variable with incomplete type 'S1'}} expected-warning {{Type 'const S2' is not trivially copyable and not guaranteed to be mapped correctly}} expected-warning {{Type 'const S3' is not trivially copyable and not guaranteed to be mapped correctly}} expected-error {{incomplete type 'S1' where a complete type is required}} expected-error {{no matching constructor for initialization of 'S3'}} + #pragma omp distribute firstprivate (a, b, c, d, f) // expected-error {{firstprivate variable with incomplete type 'S1'}} expected-warning {{type 'const S2' is not trivially copyable and not guaranteed to be mapped correctly}} expected-warning {{type 'const S3' is not trivially copyable and not guaranteed to be mapped correctly}} expected-error {{incomplete type 'S1' where a complete type is required}} expected-error {{no matching constructor for initialization of 'S3'}} for (i = 0; i < argc; ++i) foo(); #pragma omp target #pragma omp teams @@ -103,11 +103,11 @@ int main(int argc, char **argv) { for (i = 0; i < argc; ++i) foo(); #pragma omp target #pragma omp teams - #pragma omp distribute firstprivate(ba) // expected-warning {{Type 'const S2[5]' is not trivially copyable and not guaranteed to be mapped correctly}} + #pragma omp distribute firstprivate(ba) // expected-warning {{type 'const S2[5]' is not trivially copyable and not guaranteed to be mapped correctly}} for (i = 0; i < argc; ++i) foo(); #pragma omp target #pragma omp teams - #pragma omp distribute firstprivate(ca) // expected-error {{no matching constructor for initialization of 'S3'}} expected-warning {{Type 'const S3[5]' is not trivially copyable and not guaranteed to be mapped correctly}} + #pragma omp distribute firstprivate(ca) // expected-error {{no matching constructor for initialization of 'S3'}} expected-warning {{type 'const S3[5]' is not trivially copyable and not guaranteed to be mapped correctly}} for (i = 0; i < argc; ++i) foo(); #pragma omp target #pragma omp teams diff --git a/clang/test/OpenMP/distribute_parallel_for_firstprivate_messages.cpp b/clang/test/OpenMP/distribute_parallel_for_firstprivate_messages.cpp index 84d6337be34b..4bed1fe2c3a3 100644 --- a/clang/test/OpenMP/distribute_parallel_for_firstprivate_messages.cpp +++ b/clang/test/OpenMP/distribute_parallel_for_firstprivate_messages.cpp @@ -119,7 +119,7 @@ int foomain(int argc, char **argv) { ++k; #pragma omp target #pragma omp teams -#pragma omp distribute parallel for firstprivate(a, b) // expected-error {{firstprivate variable with incomplete type 'S1'}} expected-warning {{Type 'const S2' is not trivially copyable and not guaranteed to be mapped correctly}} +#pragma omp distribute parallel for firstprivate(a, b) // expected-error {{firstprivate variable with incomplete type 'S1'}} expected-warning {{type 'const S2' is not trivially copyable and not guaranteed to be mapped correctly}} for (int k = 0; k < argc; ++k) ++k; #pragma omp target @@ -129,7 +129,7 @@ int foomain(int argc, char **argv) { ++k; #pragma omp target #pragma omp teams -#pragma omp distribute parallel for firstprivate(e, g) // expected-error {{calling a private constructor of class 'S4'}} expected-error {{calling a private constructor of class 'S5'}} expected-warning {{Type 'S4' is not trivially copyable and not guaranteed to be mapped correctly}} expected-warning {{Type 'S5' is not trivially copyable and not guaranteed to be mapped correctly}} +#pragma omp distribute parallel for firstprivate(e, g) // expected-error {{calling a private constructor of class 'S4'}} expected-error {{calling a private constructor of class 'S5'}} expected-warning {{type 'S4' is not trivially copyable and not guaranteed to be mapped correctly}} expected-warning {{type 'S5' is not trivially copyable and not guaranteed to be mapped correctly}} for (int k = 0; k < argc; ++k) ++k; #pragma omp target @@ -241,7 +241,7 @@ int main(int argc, char **argv) { foo(); #pragma omp target #pragma omp teams -#pragma omp distribute parallel for firstprivate(a, b, c, d, f) // expected-error {{firstprivate variable with incomplete type 'S1'}} expected-error {{incomplete type 'S1' where a complete type is required}} expected-warning {{Type 'const S2' is not trivially copyable and not guaranteed to be mapped correctly}} expected-warning {{Type 'const S3' is not trivially copyable and not guaranteed to be mapped correctly}} +#pragma omp distribute parallel for firstprivate(a, b, c, d, f) // expected-error {{firstprivate variable with incomplete type 'S1'}} expected-error {{incomplete type 'S1' where a complete type is required}} expected-warning {{type 'const S2' is not trivially copyable and not guaranteed to be mapped correctly}} expected-warning {{type 'const S3' is not trivially copyable and not guaranteed to be mapped correctly}} for (i = 0; i < argc; ++i) foo(); #pragma omp target @@ -256,12 +256,12 @@ int main(int argc, char **argv) { foo(); #pragma omp target #pragma omp teams -#pragma omp distribute parallel for firstprivate(ba) // expected-warning {{Type 'const S2[5]' is not trivially copyable and not guaranteed to be mapped correctly}} +#pragma omp distribute parallel for firstprivate(ba) // expected-warning {{type 'const S2[5]' is not trivially copyable and not guaranteed to be mapped correctly}} for (i = 0; i < argc; ++i) foo(); #pragma omp target #pragma omp teams -#pragma omp distribute parallel for firstprivate(ca) // expected-warning {{Type 'const S3[5]' is not trivially copyable and not guaranteed to be mapped correctly}} +#pragma omp distribute parallel for firstprivate(ca) // expected-warning {{type 'const S3[5]' is not trivially copyable and not guaranteed to be mapped correctly}} for (i = 0; i < argc; ++i) foo(); #pragma omp target @@ -292,12 +292,12 @@ int main(int argc, char **argv) { foo(); #pragma omp target #pragma omp teams -#pragma omp distribute parallel for firstprivate(e, g) // expected-error {{calling a private constructor of class 'S4'}} expected-error {{calling a private constructor of class 'S5'}} expected-warning {{Type 'S4' is not trivially copyable and not guaranteed to be mapped correctly}} expected-warning {{Type 'S5' is not trivially copyable and not guaranteed to be mapped correctly}} +#pragma omp distribute parallel for firstprivate(e, g) // expected-error {{calling a private constructor of class 'S4'}} expected-error {{calling a private constructor of class 'S5'}} expected-warning {{type 'S4' is not trivially copyable and not guaranteed to be mapped correctly}} expected-warning {{type 'S5' is not trivially copyable and not guaranteed to be mapped correctly}} for (i = 0; i < argc; ++i) foo(); #pragma omp target #pragma omp teams -#pragma omp distribute parallel for firstprivate(m) // expected-warning {{Type 'S3' is not trivially copyable and not guaranteed to be mapped correctly}} +#pragma omp distribute parallel for firstprivate(m) // expected-warning {{type 'S3' is not trivially copyable and not guaranteed to be mapped correctly}} for (i = 0; i < argc; ++i) foo(); #pragma omp target @@ -329,13 +329,13 @@ int main(int argc, char **argv) { // expected-error@+3 {{lastprivate variable cannot be firstprivate}} expected-note@+3 {{defined as lastprivate}} #pragma omp target #pragma omp teams -#pragma omp distribute parallel for lastprivate(g) firstprivate(g) // expected-warning {{Type 'S5' is not trivially copyable and not guaranteed to be mapped correctly}} +#pragma omp distribute parallel for lastprivate(g) firstprivate(g) // expected-warning {{type 'S5' is not trivially copyable and not guaranteed to be mapped correctly}} for (i = 0; i < argc; ++i) foo(); // expected-error@+3 {{lastprivate variable cannot be firstprivate}} expected-note@+3 {{defined as lastprivate}} #pragma omp target #pragma omp teams -#pragma omp distribute parallel for lastprivate(n) firstprivate(n) // expected-error {{calling a private constructor of class 'S6'}} expected-warning {{Type 'S6' is not trivially copyable and not guaranteed to be mapped correctly}} +#pragma omp distribute parallel for lastprivate(n) firstprivate(n) // expected-error {{calling a private constructor of class 'S6'}} expected-warning {{type 'S6' is not trivially copyable and not guaranteed to be mapped correctly}} for (i = 0; i < argc; ++i) foo(); #pragma omp parallel diff --git a/clang/test/OpenMP/distribute_parallel_for_lastprivate_messages.cpp b/clang/test/OpenMP/distribute_parallel_for_lastprivate_messages.cpp index f403922e14e8..0a0962ef57c1 100644 --- a/clang/test/OpenMP/distribute_parallel_for_lastprivate_messages.cpp +++ b/clang/test/OpenMP/distribute_parallel_for_lastprivate_messages.cpp @@ -119,7 +119,7 @@ int foomain(int argc, char **argv) { ++k; #pragma omp target #pragma omp teams -#pragma omp distribute parallel for lastprivate(a, b) // expected-error {{lastprivate variable with incomplete type 'S1'}} expected-warning {{Type 'const S2' is not trivially copyable and not guaranteed to be mapped correctly}} +#pragma omp distribute parallel for lastprivate(a, b) // expected-error {{lastprivate variable with incomplete type 'S1'}} expected-warning {{type 'const S2' is not trivially copyable and not guaranteed to be mapped correctly}} for (int k = 0; k < argc; ++k) ++k; #pragma omp target @@ -129,7 +129,7 @@ int foomain(int argc, char **argv) { ++k; #pragma omp target #pragma omp teams -#pragma omp distribute parallel for lastprivate(e, g) // expected-error 2 {{calling a private constructor of class 'S4'}} expected-warning 2 {{Type 'S4' is not trivially copyable and not guaranteed to be mapped correctly}} +#pragma omp distribute parallel for lastprivate(e, g) // expected-error 2 {{calling a private constructor of class 'S4'}} expected-warning 2 {{type 'S4' is not trivially copyable and not guaranteed to be mapped correctly}} for (int k = 0; k < argc; ++k) ++k; #pragma omp target @@ -228,7 +228,7 @@ int main(int argc, char **argv) { foo(); #pragma omp target #pragma omp teams -#pragma omp distribute parallel for lastprivate(a, b, c, d, f) // expected-error {{lastprivate variable with incomplete type 'S1'}} expected-error 1 {{const-qualified variable without mutable fields cannot be lastprivate}} expected-error 2 {{const-qualified variable cannot be lastprivate}} expected-error {{incomplete type 'S1' where a complete type is required}} expected-warning {{Type 'const S2' is not trivially copyable and not guaranteed to be mapped correctly}} expected-warning {{Type 'const S3' is not trivially copyable and not guaranteed to be mapped correctly}} +#pragma omp distribute parallel for lastprivate(a, b, c, d, f) // expected-error {{lastprivate variable with incomplete type 'S1'}} expected-error 1 {{const-qualified variable without mutable fields cannot be lastprivate}} expected-error 2 {{const-qualified variable cannot be lastprivate}} expected-error {{incomplete type 'S1' where a complete type is required}} expected-warning {{type 'const S2' is not trivially copyable and not guaranteed to be mapped correctly}} expected-warning {{type 'const S3' is not trivially copyable and not guaranteed to be mapped correctly}} for (i = 0; i < argc; ++i) foo(); #pragma omp target @@ -243,12 +243,12 @@ int main(int argc, char **argv) { foo(); #pragma omp target #pragma omp teams -#pragma omp distribute parallel for lastprivate(ba) // expected-warning {{Type 'const S2[5]' is not trivially copyable and not guaranteed to be mapped correctly}} +#pragma omp distribute parallel for lastprivate(ba) // expected-warning {{type 'const S2[5]' is not trivially copyable and not guaranteed to be mapped correctly}} for (i = 0; i < argc; ++i) foo(); #pragma omp target #pragma omp teams -#pragma omp distribute parallel for lastprivate(ca) // expected-error {{const-qualified variable without mutable fields cannot be lastprivate}} expected-warning {{Type 'const S3[5]' is not trivially copyable and not guaranteed to be mapped correctly}} +#pragma omp distribute parallel for lastprivate(ca) // expected-error {{const-qualified variable without mutable fields cannot be lastprivate}} expected-warning {{type 'const S3[5]' is not trivially copyable and not guaranteed to be mapped correctly}} for (i = 0; i < argc; ++i) foo(); #pragma omp target @@ -279,12 +279,12 @@ int main(int argc, char **argv) { foo(); #pragma omp target #pragma omp teams -#pragma omp distribute parallel for lastprivate(e, g) // expected-error {{calling a private constructor of class 'S4'}} expected-error {{calling a private constructor of class 'S5'}} expected-warning {{Type 'S4' is not trivially copyable and not guaranteed to be mapped correctly}} expected-warning {{Type 'S5' is not trivially copyable and not guaranteed to be mapped correctly}} +#pragma omp distribute parallel for lastprivate(e, g) // expected-error {{calling a private constructor of class 'S4'}} expected-error {{calling a private constructor of class 'S5'}} expected-warning {{type 'S4' is not trivially copyable and not guaranteed to be mapped correctly}} expected-warning {{type 'S5' is not trivially copyable and not guaranteed to be mapped correctly}} for (i = 0; i < argc; ++i) foo(); #pragma omp target #pragma omp teams -#pragma omp distribute parallel for lastprivate(m) // expected-error {{'operator=' is a private member of 'S3'}} expected-warning {{Type 'S3' is not trivially copyable and not guaranteed to be mapped correctly}} +#pragma omp distribute parallel for lastprivate(m) // expected-error {{'operator=' is a private member of 'S3'}} expected-warning {{type 'S3' is not trivially copyable and not guaranteed to be mapped correctly}} for (i = 0; i < argc; ++i) foo(); #pragma omp target @@ -325,13 +325,13 @@ int main(int argc, char **argv) { // expected-error@+3 {{firstprivate variable cannot be lastprivate}} expected-note@+3 {{defined as firstprivate}} #pragma omp target #pragma omp teams -#pragma omp distribute parallel for firstprivate(m) lastprivate(m) // expected-warning {{Type 'S3' is not trivially copyable and not guaranteed to be mapped correctly}} +#pragma omp distribute parallel for firstprivate(m) lastprivate(m) // expected-warning {{type 'S3' is not trivially copyable and not guaranteed to be mapped correctly}} for (i = 0; i < argc; ++i) foo(); // expected-error@+3 {{lastprivate variable cannot be firstprivate}} expected-note@+3 {{defined as lastprivate}} #pragma omp target #pragma omp teams -#pragma omp distribute parallel for lastprivate(n) firstprivate(n) // expected-error {{calling a private constructor of class 'S6'}} expected-warning {{Type 'S6' is not trivially copyable and not guaranteed to be mapped correctly}} +#pragma omp distribute parallel for lastprivate(n) firstprivate(n) // expected-error {{calling a private constructor of class 'S6'}} expected-warning {{type 'S6' is not trivially copyable and not guaranteed to be mapped correctly}} for (i = 0; i < argc; ++i) foo(); static int si; diff --git a/clang/test/OpenMP/distribute_parallel_for_private_messages.cpp b/clang/test/OpenMP/distribute_parallel_for_private_messages.cpp index d25598e46f81..2e0e75096a26 100644 --- a/clang/test/OpenMP/distribute_parallel_for_private_messages.cpp +++ b/clang/test/OpenMP/distribute_parallel_for_private_messages.cpp @@ -50,7 +50,7 @@ public: #pragma omp target #pragma omp teams #pragma omp distribute parallel for private(a) private(this->a) private(s.a) // expected-error {{expected variable name or data member of current class}} - for (int k = 0; k < s.a; ++k) // expected-warning {{Type 'S5' is not trivially copyable and not guaranteed to be mapped correctly}} + for (int k = 0; k < s.a; ++k) // expected-warning {{type 'S5' is not trivially copyable and not guaranteed to be mapped correctly}} ++s.a; return *this; } diff --git a/clang/test/OpenMP/distribute_parallel_for_reduction_messages.cpp b/clang/test/OpenMP/distribute_parallel_for_reduction_messages.cpp index 6b3d9da9a3a6..864fb597214b 100644 --- a/clang/test/OpenMP/distribute_parallel_for_reduction_messages.cpp +++ b/clang/test/OpenMP/distribute_parallel_for_reduction_messages.cpp @@ -187,7 +187,7 @@ T tmain(T argc) { foo(); #pragma omp target #pragma omp teams -#pragma omp distribute parallel for reduction(+ : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 3 {{const-qualified variable cannot be reduction}} expected-error 2 {{'operator+' is a private member of 'S2'}} expected-warning 2 {{Type 'S2' is not trivially copyable and not guaranteed to be mapped correctly}} expected-warning 2 {{Type 'S3' is not trivially copyable and not guaranteed to be mapped correctly}} +#pragma omp distribute parallel for reduction(+ : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 3 {{const-qualified variable cannot be reduction}} expected-error 2 {{'operator+' is a private member of 'S2'}} expected-warning 2 {{type 'S2' is not trivially copyable and not guaranteed to be mapped correctly}} expected-warning 2 {{type 'S3' is not trivially copyable and not guaranteed to be mapped correctly}} for (int i = 0; i < 10; ++i) foo(); #pragma omp target @@ -232,7 +232,7 @@ T tmain(T argc) { foo(); #pragma omp target #pragma omp teams -#pragma omp distribute parallel for reduction(+ : h, k) // expected-error {{threadprivate or thread local variable cannot be reduction}} expected-warning 2 {{Type 'S3' is not trivially copyable and not guaranteed to be mapped correctly}} +#pragma omp distribute parallel for reduction(+ : h, k) // expected-error {{threadprivate or thread local variable cannot be reduction}} expected-warning 2 {{type 'S3' is not trivially copyable and not guaranteed to be mapped correctly}} for (int i = 0; i < 10; ++i) foo(); #pragma omp target @@ -371,12 +371,12 @@ int main(int argc, char **argv) { foo(); #pragma omp target #pragma omp teams -#pragma omp distribute parallel for reduction(+ : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 2 {{const-qualified variable cannot be reduction}} expected-error {{'operator+' is a private member of 'S2'}} expected-error {{incomplete type 'S1' where a complete type is required}} expected-warning {{Type 'S2' is not trivially copyable and not guaranteed to be mapped correctly}} expected-warning {{Type 'S3' is not trivially copyable and not guaranteed to be mapped correctly}} +#pragma omp distribute parallel for reduction(+ : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 2 {{const-qualified variable cannot be reduction}} expected-error {{'operator+' is a private member of 'S2'}} expected-error {{incomplete type 'S1' where a complete type is required}} expected-warning {{type 'S2' is not trivially copyable and not guaranteed to be mapped correctly}} expected-warning {{type 'S3' is not trivially copyable and not guaranteed to be mapped correctly}} for (int i = 0; i < 10; ++i) foo(); #pragma omp target #pragma omp teams -#pragma omp distribute parallel for reduction(min : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 2 {{arguments of OpenMP clause 'reduction' for 'min' or 'max' must be of arithmetic type}} expected-error 2 {{const-qualified variable cannot be reduction}} expected-error {{incomplete type 'S1' where a complete type is required}} expected-warning {{Type 'S2' is not trivially copyable and not guaranteed to be mapped correctly}} expected-warning {{Type 'S3' is not trivially copyable and not guaranteed to be mapped correctly}} +#pragma omp distribute parallel for reduction(min : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 2 {{arguments of OpenMP clause 'reduction' for 'min' or 'max' must be of arithmetic type}} expected-error 2 {{const-qualified variable cannot be reduction}} expected-error {{incomplete type 'S1' where a complete type is required}} expected-warning {{type 'S2' is not trivially copyable and not guaranteed to be mapped correctly}} expected-warning {{type 'S3' is not trivially copyable and not guaranteed to be mapped correctly}} for (int i = 0; i < 10; ++i) foo(); #pragma omp target @@ -386,12 +386,12 @@ int main(int argc, char **argv) { foo(); #pragma omp target #pragma omp teams -#pragma omp distribute parallel for reduction(+ : ba) // expected-error {{const-qualified variable cannot be reduction}} expected-warning {{Type 'const S2[5]' is not trivially copyable and not guaranteed to be mapped correctly}} +#pragma omp distribute parallel for reduction(+ : ba) // expected-error {{const-qualified variable cannot be reduction}} expected-warning {{type 'const S2[5]' is not trivially copyable and not guaranteed to be mapped correctly}} for (int i = 0; i < 10; ++i) foo(); #pragma omp target #pragma omp teams -#pragma omp distribute parallel for reduction(* : ca) // expected-error {{const-qualified variable cannot be reduction}} expected-warning {{Type 'const S3[5]' is not trivially copyable and not guaranteed to be mapped correctly}} +#pragma omp distribute parallel for reduction(* : ca) // expected-error {{const-qualified variable cannot be reduction}} expected-warning {{type 'const S3[5]' is not trivially copyable and not guaranteed to be mapped correctly}} for (int i = 0; i < 10; ++i) foo(); #pragma omp target @@ -416,12 +416,12 @@ int main(int argc, char **argv) { foo(); #pragma omp target #pragma omp teams -#pragma omp distribute parallel for reduction(& : e, g) // expected-error {{calling a private constructor of class 'S4'}} expected-error {{calling a private constructor of class 'S5'}} expected-error {{invalid operands to binary expression ('S5' and 'S5')}} expected-warning {{Type 'S4' is not trivially copyable and not guaranteed to be mapped correctly}} expected-warning {{Type 'S5' is not trivially copyable and not guaranteed to be mapped correctly}} +#pragma omp distribute parallel for reduction(& : e, g) // expected-error {{calling a private constructor of class 'S4'}} expected-error {{calling a private constructor of class 'S5'}} expected-error {{invalid operands to binary expression ('S5' and 'S5')}} expected-warning {{type 'S4' is not trivially copyable and not guaranteed to be mapped correctly}} expected-warning {{type 'S5' is not trivially copyable and not guaranteed to be mapped correctly}} for (int i = 0; i < 10; ++i) foo(); #pragma omp target #pragma omp teams -#pragma omp distribute parallel for reduction(+ : h, k, B::x) // expected-error 2 {{threadprivate or thread local variable cannot be reduction}} expected-warning {{Type 'S3' is not trivially copyable and not guaranteed to be mapped correctly}} +#pragma omp distribute parallel for reduction(+ : h, k, B::x) // expected-error 2 {{threadprivate or thread local variable cannot be reduction}} expected-warning {{type 'S3' is not trivially copyable and not guaranteed to be mapped correctly}} for (int i = 0; i < 10; ++i) foo(); #pragma omp target @@ -437,12 +437,12 @@ int main(int argc, char **argv) { #pragma omp parallel private(k) #pragma omp target #pragma omp teams -#pragma omp distribute parallel for reduction(+ : p), reduction(+ : p) // expected-error 2 {{argument of OpenMP clause 'reduction' must reference the same object in all threads}} expected-warning {{Type 'S3' is not trivially copyable and not guaranteed to be mapped correctly}} +#pragma omp distribute parallel for reduction(+ : p), reduction(+ : p) // expected-error 2 {{argument of OpenMP clause 'reduction' must reference the same object in all threads}} expected-warning {{type 'S3' is not trivially copyable and not guaranteed to be mapped correctly}} for (int i = 0; i < 10; ++i) foo(); #pragma omp target #pragma omp teams -#pragma omp distribute parallel for reduction(+ : p), reduction(+ : p) // expected-error {{variable can appear only once in OpenMP 'reduction' clause}} expected-note {{previously referenced here}} expected-warning {{Type 'S3' is not trivially copyable and not guaranteed to be mapped correctly}} +#pragma omp distribute parallel for reduction(+ : p), reduction(+ : p) // expected-error {{variable can appear only once in OpenMP 'reduction' clause}} expected-note {{previously referenced here}} expected-warning {{type 'S3' is not trivially copyable and not guaranteed to be mapped correctly}} for (int i = 0; i < 10; ++i) foo(); #pragma omp target diff --git a/clang/test/OpenMP/distribute_parallel_for_simd_private_messages.cpp b/clang/test/OpenMP/distribute_parallel_for_simd_private_messages.cpp index 43bc6ad8e637..0cb8c01625db 100644 --- a/clang/test/OpenMP/distribute_parallel_for_simd_private_messages.cpp +++ b/clang/test/OpenMP/distribute_parallel_for_simd_private_messages.cpp @@ -50,7 +50,7 @@ public: #pragma omp target #pragma omp teams #pragma omp distribute parallel for simd private(a) private(this->a) private(s.a) // expected-error {{expected variable name or data member of current class}} - for (int k = 0; k < s.a; ++k) // expected-warning {{Type 'S5' is not trivially copyable and not guaranteed to be mapped correctly}} + for (int k = 0; k < s.a; ++k) // expected-warning {{type 'S5' is not trivially copyable and not guaranteed to be mapped correctly}} ++s.a; return *this; } diff --git a/clang/test/OpenMP/distribute_parallel_for_simd_shared_messages.cpp b/clang/test/OpenMP/distribute_parallel_for_simd_shared_messages.cpp index 7c83e4c674c6..6dc6e777fb33 100644 --- a/clang/test/OpenMP/distribute_parallel_for_simd_shared_messages.cpp +++ b/clang/test/OpenMP/distribute_parallel_for_simd_shared_messages.cpp @@ -117,7 +117,7 @@ T tmain(T argc, S **argv) { #pragma omp target #pragma omp teams -#pragma omp distribute parallel for simd shared (a, b, c, d, f) // expected-error {{incomplete type 'S1' where a complete type is required}} expected-warning {{Type 'const S2' is not trivially copyable and not guaranteed to be mapped correctly}} expected-warning {{Type 'const S3' is not trivially copyable and not guaranteed to be mapped correctly}} +#pragma omp distribute parallel for simd shared (a, b, c, d, f) // expected-error {{incomplete type 'S1' where a complete type is required}} expected-warning {{type 'const S2' is not trivially copyable and not guaranteed to be mapped correctly}} expected-warning {{type 'const S3' is not trivially copyable and not guaranteed to be mapped correctly}} for(int k = 0 ; k < n ; k++) { acc++; } @@ -131,14 +131,14 @@ T tmain(T argc, S **argv) { #pragma omp target #pragma omp teams -#pragma omp distribute parallel for simd shared(ba) // expected-warning {{Type 'const S2[5]' is not trivially copyable and not guaranteed to be mapped correctly}} +#pragma omp distribute parallel for simd shared(ba) // expected-warning {{type 'const S2[5]' is not trivially copyable and not guaranteed to be mapped correctly}} for(int k = 0 ; k < n ; k++) { acc++; } #pragma omp target #pragma omp teams -#pragma omp distribute parallel for simd shared(ca) // expected-warning {{Type 'const S3[5]' is not trivially copyable and not guaranteed to be mapped correctly}} +#pragma omp distribute parallel for simd shared(ca) // expected-warning {{type 'const S3[5]' is not trivially copyable and not guaranteed to be mapped correctly}} for(int k = 0 ; k < n ; k++) { acc++; } @@ -152,7 +152,7 @@ T tmain(T argc, S **argv) { #pragma omp target #pragma omp teams -#pragma omp distribute parallel for simd shared(e, g) // expected-warning {{Type 'S4' is not trivially copyable and not guaranteed to be mapped correctly}} expected-warning {{Type 'S5' is not trivially copyable and not guaranteed to be mapped correctly}} +#pragma omp distribute parallel for simd shared(e, g) // expected-warning {{type 'S4' is not trivially copyable and not guaranteed to be mapped correctly}} expected-warning {{type 'S5' is not trivially copyable and not guaranteed to be mapped correctly}} for(int k = 0 ; k < n ; k++) { acc++; } @@ -291,7 +291,7 @@ int main(int argc, char **argv) { #pragma omp target #pragma omp teams -#pragma omp distribute parallel for simd shared (a, b, c, d, f) // expected-error {{incomplete type 'S1' where a complete type is required}} expected-warning {{Type 'const S2' is not trivially copyable and not guaranteed to be mapped correctly}} expected-warning {{Type 'const S3' is not trivially copyable and not guaranteed to be mapped correctly}} +#pragma omp distribute parallel for simd shared (a, b, c, d, f) // expected-error {{incomplete type 'S1' where a complete type is required}} expected-warning {{type 'const S2' is not trivially copyable and not guaranteed to be mapped correctly}} expected-warning {{type 'const S3' is not trivially copyable and not guaranteed to be mapped correctly}} for(int k = 0 ; k < n ; k++) { acc++; } @@ -305,14 +305,14 @@ int main(int argc, char **argv) { #pragma omp target #pragma omp teams -#pragma omp distribute parallel for simd shared(ba) // expected-warning {{Type 'const S2[5]' is not trivially copyable and not guaranteed to be mapped correctly}} +#pragma omp distribute parallel for simd shared(ba) // expected-warning {{type 'const S2[5]' is not trivially copyable and not guaranteed to be mapped correctly}} for(int k = 0 ; k < n ; k++) { acc++; } #pragma omp target #pragma omp teams -#pragma omp distribute parallel for simd shared(ca) // expected-warning {{Type 'const S3[5]' is not trivially copyable and not guaranteed to be mapped correctly}} +#pragma omp distribute parallel for simd shared(ca) // expected-warning {{type 'const S3[5]' is not trivially copyable and not guaranteed to be mapped correctly}} for(int k = 0 ; k < n ; k++) { acc++; } @@ -326,7 +326,7 @@ int main(int argc, char **argv) { #pragma omp target #pragma omp teams -#pragma omp distribute parallel for simd shared(e, g) // expected-warning {{Type 'S4' is not trivially copyable and not guaranteed to be mapped correctly}} expected-warning {{Type 'S5' is not trivially copyable and not guaranteed to be mapped correctly}} +#pragma omp distribute parallel for simd shared(e, g) // expected-warning {{type 'S4' is not trivially copyable and not guaranteed to be mapped correctly}} expected-warning {{type 'S5' is not trivially copyable and not guaranteed to be mapped correctly}} for(int k = 0 ; k < n ; k++) { acc++; } diff --git a/clang/test/OpenMP/distribute_simd_firstprivate_messages.cpp b/clang/test/OpenMP/distribute_simd_firstprivate_messages.cpp index 43057fe5bacc..bc1dfcfe7ab4 100644 --- a/clang/test/OpenMP/distribute_simd_firstprivate_messages.cpp +++ b/clang/test/OpenMP/distribute_simd_firstprivate_messages.cpp @@ -111,7 +111,7 @@ int foomain(int argc, char **argv) { ++k; #pragma omp target #pragma omp teams -#pragma omp distribute simd firstprivate(z, a, b) // expected-error {{firstprivate variable with incomplete type 'S1'}} expected-warning {{Type 'const S2' is not trivially copyable and not guaranteed to be mapped correctly}} +#pragma omp distribute simd firstprivate(z, a, b) // expected-error {{firstprivate variable with incomplete type 'S1'}} expected-warning {{type 'const S2' is not trivially copyable and not guaranteed to be mapped correctly}} for (int k = 0; k < argc; ++k) ++k; #pragma omp target @@ -121,7 +121,7 @@ int foomain(int argc, char **argv) { ++k; #pragma omp target #pragma omp teams -#pragma omp distribute simd firstprivate(e, g) // expected-error {{calling a private constructor of class 'S4'}} expected-error {{calling a private constructor of class 'S5'}} expected-warning {{Type 'S4' is not trivially copyable and not guaranteed to be mapped correctly}} expected-warning {{Type 'S5' is not trivially copyable and not guaranteed to be mapped correctly}} +#pragma omp distribute simd firstprivate(e, g) // expected-error {{calling a private constructor of class 'S4'}} expected-error {{calling a private constructor of class 'S5'}} expected-warning {{type 'S4' is not trivially copyable and not guaranteed to be mapped correctly}} expected-warning {{type 'S5' is not trivially copyable and not guaranteed to be mapped correctly}} for (int k = 0; k < argc; ++k) ++k; #pragma omp target @@ -233,7 +233,7 @@ int main(int argc, char **argv) { foo(); #pragma omp target #pragma omp teams -#pragma omp distribute simd firstprivate(a, b, c, d, f) // expected-error {{firstprivate variable with incomplete type 'S1'}} expected-error {{incomplete type 'S1' where a complete type is required}} expected-warning {{Type 'const S2' is not trivially copyable and not guaranteed to be mapped correctly}} expected-warning {{Type 'const S3' is not trivially copyable and not guaranteed to be mapped correctly}} +#pragma omp distribute simd firstprivate(a, b, c, d, f) // expected-error {{firstprivate variable with incomplete type 'S1'}} expected-error {{incomplete type 'S1' where a complete type is required}} expected-warning {{type 'const S2' is not trivially copyable and not guaranteed to be mapped correctly}} expected-warning {{type 'const S3' is not trivially copyable and not guaranteed to be mapped correctly}} for (i = 0; i < argc; ++i) foo(); #pragma omp target @@ -248,12 +248,12 @@ int main(int argc, char **argv) { foo(); #pragma omp target #pragma omp teams -#pragma omp distribute simd firstprivate(ba) // expected-warning {{Type 'const S2[5]' is not trivially copyable and not guaranteed to be mapped correctly}} +#pragma omp distribute simd firstprivate(ba) // expected-warning {{type 'const S2[5]' is not trivially copyable and not guaranteed to be mapped correctly}} for (i = 0; i < argc; ++i) foo(); #pragma omp target #pragma omp teams -#pragma omp distribute simd firstprivate(ca) // expected-warning {{Type 'const S3[5]' is not trivially copyable and not guaranteed to be mapped correctly}} +#pragma omp distribute simd firstprivate(ca) // expected-warning {{type 'const S3[5]' is not trivially copyable and not guaranteed to be mapped correctly}} for (i = 0; i < argc; ++i) foo(); #pragma omp target @@ -284,12 +284,12 @@ int main(int argc, char **argv) { foo(); #pragma omp target #pragma omp teams -#pragma omp distribute simd firstprivate(e, g) // expected-error {{calling a private constructor of class 'S4'}} expected-error {{calling a private constructor of class 'S5'}} expected-warning {{Type 'S4' is not trivially copyable and not guaranteed to be mapped correctly}} expected-warning {{Type 'S5' is not trivially copyable and not guaranteed to be mapped correctly}} +#pragma omp distribute simd firstprivate(e, g) // expected-error {{calling a private constructor of class 'S4'}} expected-error {{calling a private constructor of class 'S5'}} expected-warning {{type 'S4' is not trivially copyable and not guaranteed to be mapped correctly}} expected-warning {{type 'S5' is not trivially copyable and not guaranteed to be mapped correctly}} for (i = 0; i < argc; ++i) foo(); #pragma omp target #pragma omp teams -#pragma omp distribute simd firstprivate(m) // expected-warning {{Type 'S3' is not trivially copyable and not guaranteed to be mapped correctly}} +#pragma omp distribute simd firstprivate(m) // expected-warning {{type 'S3' is not trivially copyable and not guaranteed to be mapped correctly}} for (i = 0; i < argc; ++i) foo(); #pragma omp target @@ -321,13 +321,13 @@ int main(int argc, char **argv) { // expected-error@+3 {{lastprivate variable cannot be firstprivate}} expected-note@+3 {{defined as lastprivate}} #pragma omp target #pragma omp teams -#pragma omp distribute simd lastprivate(g) firstprivate(g) //expected-warning {{Type 'S5' is not trivially copyable and not guaranteed to be mapped correctly}} +#pragma omp distribute simd lastprivate(g) firstprivate(g) //expected-warning {{type 'S5' is not trivially copyable and not guaranteed to be mapped correctly}} for (i = 0; i < argc; ++i) foo(); // expected-error@+3 {{lastprivate variable cannot be firstprivate}} expected-note@+3 {{defined as lastprivate}} #pragma omp target #pragma omp teams -#pragma omp distribute simd lastprivate(n) firstprivate(n) // expected-error {{calling a private constructor of class 'S6'}} expected-warning {{Type 'S6' is not trivially copyable and not guaranteed to be mapped correctly}} +#pragma omp distribute simd lastprivate(n) firstprivate(n) // expected-error {{calling a private constructor of class 'S6'}} expected-warning {{type 'S6' is not trivially copyable and not guaranteed to be mapped correctly}} for (i = 0; i < argc; ++i) foo(); #pragma omp parallel diff --git a/clang/test/OpenMP/distribute_simd_lastprivate_messages.cpp b/clang/test/OpenMP/distribute_simd_lastprivate_messages.cpp index 7658288242ab..379f57547498 100644 --- a/clang/test/OpenMP/distribute_simd_lastprivate_messages.cpp +++ b/clang/test/OpenMP/distribute_simd_lastprivate_messages.cpp @@ -120,7 +120,7 @@ int foomain(int argc, char **argv) { ++k; #pragma omp target #pragma omp teams -#pragma omp distribute simd lastprivate(a, b) // expected-error {{lastprivate variable with incomplete type 'S1'}} expected-warning {{Type 'const S2' is not trivially copyable and not guaranteed to be mapped correctly}} +#pragma omp distribute simd lastprivate(a, b) // expected-error {{lastprivate variable with incomplete type 'S1'}} expected-warning {{type 'const S2' is not trivially copyable and not guaranteed to be mapped correctly}} for (int k = 0; k < argc; ++k) ++k; #pragma omp target @@ -130,7 +130,7 @@ int foomain(int argc, char **argv) { ++k; #pragma omp target #pragma omp teams -#pragma omp distribute simd lastprivate(e, g) // expected-error 2 {{calling a private constructor of class 'S4'}} expected-warning 2 {{Type 'S4' is not trivially copyable and not guaranteed to be mapped correctly}} +#pragma omp distribute simd lastprivate(e, g) // expected-error 2 {{calling a private constructor of class 'S4'}} expected-warning 2 {{type 'S4' is not trivially copyable and not guaranteed to be mapped correctly}} for (int k = 0; k < argc; ++k) ++k; #pragma omp target @@ -229,7 +229,7 @@ int main(int argc, char **argv) { foo(); #pragma omp target #pragma omp teams -#pragma omp distribute simd lastprivate(a, b, c, d, f) // expected-error {{lastprivate variable with incomplete type 'S1'}} expected-error 1 {{const-qualified variable without mutable fields cannot be lastprivate}} expected-error 2 {{const-qualified variable cannot be lastprivate}} expected-error {{incomplete type 'S1' where a complete type is required}} expected-warning {{Type 'const S2' is not trivially copyable and not guaranteed to be mapped correctly}} expected-warning {{Type 'const S3' is not trivially copyable and not guaranteed to be mapped correctly}} +#pragma omp distribute simd lastprivate(a, b, c, d, f) // expected-error {{lastprivate variable with incomplete type 'S1'}} expected-error 1 {{const-qualified variable without mutable fields cannot be lastprivate}} expected-error 2 {{const-qualified variable cannot be lastprivate}} expected-error {{incomplete type 'S1' where a complete type is required}} expected-warning {{type 'const S2' is not trivially copyable and not guaranteed to be mapped correctly}} expected-warning {{type 'const S3' is not trivially copyable and not guaranteed to be mapped correctly}} for (i = 0; i < argc; ++i) foo(); #pragma omp target @@ -244,12 +244,12 @@ int main(int argc, char **argv) { foo(); #pragma omp target #pragma omp teams -#pragma omp distribute simd lastprivate(ba) // expected-warning {{Type 'const S2[5]' is not trivially copyable and not guaranteed to be mapped correctly}} +#pragma omp distribute simd lastprivate(ba) // expected-warning {{type 'const S2[5]' is not trivially copyable and not guaranteed to be mapped correctly}} for (i = 0; i < argc; ++i) foo(); #pragma omp target #pragma omp teams -#pragma omp distribute simd lastprivate(ca) // expected-error {{const-qualified variable without mutable fields cannot be lastprivate}} expected-warning {{Type 'const S3[5]' is not trivially copyable and not guaranteed to be mapped correctly}} +#pragma omp distribute simd lastprivate(ca) // expected-error {{const-qualified variable without mutable fields cannot be lastprivate}} expected-warning {{type 'const S3[5]' is not trivially copyable and not guaranteed to be mapped correctly}} for (i = 0; i < argc; ++i) foo(); #pragma omp target @@ -280,12 +280,12 @@ int main(int argc, char **argv) { foo(); #pragma omp target #pragma omp teams -#pragma omp distribute simd lastprivate(e, g) // expected-error {{calling a private constructor of class 'S4'}} expected-error {{calling a private constructor of class 'S5'}} expected-warning {{Type 'S4' is not trivially copyable and not guaranteed to be mapped correctly}} expected-warning {{Type 'S5' is not trivially copyable and not guaranteed to be mapped correctly}} +#pragma omp distribute simd lastprivate(e, g) // expected-error {{calling a private constructor of class 'S4'}} expected-error {{calling a private constructor of class 'S5'}} expected-warning {{type 'S4' is not trivially copyable and not guaranteed to be mapped correctly}} expected-warning {{type 'S5' is not trivially copyable and not guaranteed to be mapped correctly}} for (i = 0; i < argc; ++i) foo(); #pragma omp target #pragma omp teams -#pragma omp distribute simd lastprivate(m) // expected-error {{'operator=' is a private member of 'S3'}} expected-warning {{Type 'S3' is not trivially copyable and not guaranteed to be mapped correctly}} +#pragma omp distribute simd lastprivate(m) // expected-error {{'operator=' is a private member of 'S3'}} expected-warning {{type 'S3' is not trivially copyable and not guaranteed to be mapped correctly}} for (i = 0; i < argc; ++i) foo(); #pragma omp target @@ -326,13 +326,13 @@ int main(int argc, char **argv) { // expected-error@+3 {{firstprivate variable cannot be lastprivate}} expected-note@+3 {{defined as firstprivate}} #pragma omp target #pragma omp teams -#pragma omp distribute simd firstprivate(m) lastprivate(m) // expected-warning {{Type 'S3' is not trivially copyable and not guaranteed to be mapped correctly}} +#pragma omp distribute simd firstprivate(m) lastprivate(m) // expected-warning {{type 'S3' is not trivially copyable and not guaranteed to be mapped correctly}} for (i = 0; i < argc; ++i) foo(); // expected-error@+3 {{lastprivate variable cannot be firstprivate}} expected-note@+3 {{defined as lastprivate}} #pragma omp target #pragma omp teams -#pragma omp distribute simd lastprivate(n) firstprivate(n) // expected-error {{calling a private constructor of class 'S6'}} expected-warning {{Type 'S6' is not trivially copyable and not guaranteed to be mapped correctly}} +#pragma omp distribute simd lastprivate(n) firstprivate(n) // expected-error {{calling a private constructor of class 'S6'}} expected-warning {{type 'S6' is not trivially copyable and not guaranteed to be mapped correctly}} for (i = 0; i < argc; ++i) foo(); static int si; diff --git a/clang/test/OpenMP/distribute_simd_loop_messages.cpp b/clang/test/OpenMP/distribute_simd_loop_messages.cpp index 5a55f9569b8d..e56c7dfbddab 100644 --- a/clang/test/OpenMP/distribute_simd_loop_messages.cpp +++ b/clang/test/OpenMP/distribute_simd_loop_messages.cpp @@ -14,7 +14,7 @@ public: #pragma omp target #pragma omp teams #pragma omp distribute simd - for (int k = 0; k < s.a; ++k) // expected-warning {{Type 'S5' is not trivially copyable and not guaranteed to be mapped correctly}} + for (int k = 0; k < s.a; ++k) // expected-warning {{type 'S5' is not trivially copyable and not guaranteed to be mapped correctly}} ++s.a; return *this; } @@ -490,7 +490,7 @@ int test_with_random_access_iterator() { #pragma omp target #pragma omp teams #pragma omp distribute simd - for (GoodIter I = begin; I < end; ++I) // expected-warning 2 {{Type 'GoodIter' is not trivially copyable and not guaranteed to be mapped correctly}} + for (GoodIter I = begin; I < end; ++I) // expected-warning 2 {{type 'GoodIter' is not trivially copyable and not guaranteed to be mapped correctly}} ++I; #pragma omp target #pragma omp teams @@ -501,41 +501,41 @@ int test_with_random_access_iterator() { #pragma omp target #pragma omp teams #pragma omp distribute simd - for (GoodIter I = begin; I >= end; --I) // expected-warning 2 {{Type 'GoodIter' is not trivially copyable and not guaranteed to be mapped correctly}} + for (GoodIter I = begin; I >= end; --I) // expected-warning 2 {{type 'GoodIter' is not trivially copyable and not guaranteed to be mapped correctly}} ++I; #pragma omp target #pragma omp teams // expected-warning@+2 {{initialization clause of OpenMP for loop is not in canonical form ('var = init' or 'T var = init')}} #pragma omp distribute simd - for (GoodIter I(begin); I < end; ++I) // expected-warning 2 {{Type 'GoodIter' is not trivially copyable and not guaranteed to be mapped correctly}} + for (GoodIter I(begin); I < end; ++I) // expected-warning 2 {{type 'GoodIter' is not trivially copyable and not guaranteed to be mapped correctly}} ++I; #pragma omp target #pragma omp teams // expected-warning@+2 {{initialization clause of OpenMP for loop is not in canonical form ('var = init' or 'T var = init')}} #pragma omp distribute simd - for (GoodIter I(nullptr); I < end; ++I) // expected-warning {{Type 'GoodIter' is not trivially copyable and not guaranteed to be mapped correctly}} + for (GoodIter I(nullptr); I < end; ++I) // expected-warning {{type 'GoodIter' is not trivially copyable and not guaranteed to be mapped correctly}} ++I; #pragma omp target #pragma omp teams // expected-warning@+2 {{initialization clause of OpenMP for loop is not in canonical form ('var = init' or 'T var = init')}} #pragma omp distribute simd - for (GoodIter I(0); I < end; ++I) // expected-warning {{Type 'GoodIter' is not trivially copyable and not guaranteed to be mapped correctly}} + for (GoodIter I(0); I < end; ++I) // expected-warning {{type 'GoodIter' is not trivially copyable and not guaranteed to be mapped correctly}} ++I; #pragma omp target #pragma omp teams // expected-warning@+2 {{initialization clause of OpenMP for loop is not in canonical form ('var = init' or 'T var = init')}} #pragma omp distribute simd - for (GoodIter I(1,2); I < end; ++I) // expected-warning {{Type 'GoodIter' is not trivially copyable and not guaranteed to be mapped correctly}} + for (GoodIter I(1,2); I < end; ++I) // expected-warning {{type 'GoodIter' is not trivially copyable and not guaranteed to be mapped correctly}} ++I; #pragma omp target #pragma omp teams #pragma omp distribute simd - for (begin = GoodIter(0); begin < end; ++begin) // expected-warning 2 {{Type 'GoodIter' is not trivially copyable and not guaranteed to be mapped correctly}} + for (begin = GoodIter(0); begin < end; ++begin) // expected-warning 2 {{type 'GoodIter' is not trivially copyable and not guaranteed to be mapped correctly}} ++begin; #pragma omp target #pragma omp teams #pragma omp distribute simd - for (begin = GoodIter(1,2); begin < end; ++begin) // expected-warning 2 {{Type 'GoodIter' is not trivially copyable and not guaranteed to be mapped correctly}} + for (begin = GoodIter(1,2); begin < end; ++begin) // expected-warning 2 {{type 'GoodIter' is not trivially copyable and not guaranteed to be mapped correctly}} ++begin; #pragma omp target #pragma omp teams @@ -546,7 +546,7 @@ int test_with_random_access_iterator() { #pragma omp target #pragma omp teams #pragma omp distribute simd - for (begin = end; begin < end; ++begin) // expected-warning 2 {{Type 'GoodIter' is not trivially copyable and not guaranteed to be mapped correctly}} + for (begin = end; begin < end; ++begin) // expected-warning 2 {{type 'GoodIter' is not trivially copyable and not guaranteed to be mapped correctly}} ++begin; #pragma omp target #pragma omp teams @@ -576,7 +576,7 @@ int test_with_random_access_iterator() { #pragma omp target #pragma omp teams #pragma omp distribute simd - for (GoodIter I = begin; I >= end; I = I - 1) // expected-warning 2 {{Type 'GoodIter' is not trivially copyable and not guaranteed to be mapped correctly}} + for (GoodIter I = begin; I >= end; I = I - 1) // expected-warning 2 {{type 'GoodIter' is not trivially copyable and not guaranteed to be mapped correctly}} ++I; #pragma omp target #pragma omp teams @@ -600,7 +600,7 @@ int test_with_random_access_iterator() { #pragma omp target #pragma omp teams #pragma omp distribute simd - for (Iter0 I = begin0; I < end0; ++I) // expected-warning 2 {{Type 'Iter0' is not trivially copyable and not guaranteed to be mapped correctly}} + for (Iter0 I = begin0; I < end0; ++I) // expected-warning 2 {{type 'Iter0' is not trivially copyable and not guaranteed to be mapped correctly}} ++I; #pragma omp target @@ -608,7 +608,7 @@ int test_with_random_access_iterator() { // Initializer is constructor without params. // expected-warning@+2 {{initialization clause of OpenMP for loop is not in canonical form ('var = init' or 'T var = init')}} #pragma omp distribute simd - for (Iter0 I; I < end0; ++I) // expected-warning {{Type 'Iter0' is not trivially copyable and not guaranteed to be mapped correctly}} + for (Iter0 I; I < end0; ++I) // expected-warning {{type 'Iter0' is not trivially copyable and not guaranteed to be mapped correctly}} ++I; Iter1 begin1, end1; @@ -654,7 +654,7 @@ template class TC { // expected-note@+3 {{loop step is expected to be positive due to this condition}} // expected-error@+2 {{increment expression must cause 'I' to increase on each iteration of OpenMP for loop}} #pragma omp distribute simd - for (IT I = begin; I <= end; I += ST) { // expected-warning 2 {{Type 'GoodIter' is not trivially copyable and not guaranteed to be mapped correctly}} + for (IT I = begin; I <= end; I += ST) { // expected-warning 2 {{type 'GoodIter' is not trivially copyable and not guaranteed to be mapped correctly}} ++I; } #pragma omp distribute simd @@ -697,7 +697,7 @@ template int dotest_gt(IT begin, IT end) { #pragma omp target #pragma omp teams #pragma omp distribute simd - for (IT I = begin; I < end; I+=TC::step()) { // expected-warning 2 {{Type 'GoodIter' is not trivially copyable and not guaranteed to be mapped correctly}} + for (IT I = begin; I < end; I+=TC::step()) { // expected-warning 2 {{type 'GoodIter' is not trivially copyable and not guaranteed to be mapped correctly}} ++I; } } diff --git a/clang/test/OpenMP/distribute_simd_private_messages.cpp b/clang/test/OpenMP/distribute_simd_private_messages.cpp index 261a46ac6099..8be71938e0fa 100644 --- a/clang/test/OpenMP/distribute_simd_private_messages.cpp +++ b/clang/test/OpenMP/distribute_simd_private_messages.cpp @@ -50,7 +50,7 @@ public: #pragma omp target #pragma omp teams #pragma omp distribute simd private(a) private(this->a) private(s.a) // expected-error {{expected variable name or data member of current class}} - for (int k = 0; k < s.a; ++k) // expected-warning {{Type 'S5' is not trivially copyable and not guaranteed to be mapped correctly}} + for (int k = 0; k < s.a; ++k) // expected-warning {{type 'S5' is not trivially copyable and not guaranteed to be mapped correctly}} ++s.a; return *this; } diff --git a/clang/test/OpenMP/distribute_simd_reduction_messages.cpp b/clang/test/OpenMP/distribute_simd_reduction_messages.cpp index d27360ac9b2c..03b6ee5f4a25 100644 --- a/clang/test/OpenMP/distribute_simd_reduction_messages.cpp +++ b/clang/test/OpenMP/distribute_simd_reduction_messages.cpp @@ -187,7 +187,7 @@ T tmain(T argc) { foo(); #pragma omp target #pragma omp teams -#pragma omp distribute simd reduction(+ : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 3 {{const-qualified variable cannot be reduction}} expected-error 2 {{'operator+' is a private member of 'S2'}} expected-warning 2 {{Type 'S2' is not trivially copyable and not guaranteed to be mapped correctly}} expected-warning 2 {{Type 'S3' is not trivially copyable and not guaranteed to be mapped correctly}} +#pragma omp distribute simd reduction(+ : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 3 {{const-qualified variable cannot be reduction}} expected-error 2 {{'operator+' is a private member of 'S2'}} expected-warning 2 {{type 'S2' is not trivially copyable and not guaranteed to be mapped correctly}} expected-warning 2 {{type 'S3' is not trivially copyable and not guaranteed to be mapped correctly}} for (int i = 0; i < 10; ++i) foo(); #pragma omp target @@ -232,7 +232,7 @@ T tmain(T argc) { foo(); #pragma omp target #pragma omp teams -#pragma omp distribute simd reduction(+ : h, k) // expected-error {{threadprivate or thread local variable cannot be reduction}} expected-warning 2 {{Type 'S3' is not trivially copyable and not guaranteed to be mapped correctly}} +#pragma omp distribute simd reduction(+ : h, k) // expected-error {{threadprivate or thread local variable cannot be reduction}} expected-warning 2 {{type 'S3' is not trivially copyable and not guaranteed to be mapped correctly}} for (int i = 0; i < 10; ++i) foo(); #pragma omp target @@ -376,12 +376,12 @@ int main(int argc, char **argv) { foo(); #pragma omp target #pragma omp teams -#pragma omp distribute simd reduction(+ : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 2 {{const-qualified variable cannot be reduction}} expected-error {{'operator+' is a private member of 'S2'}} expected-warning {{Type 'S2' is not trivially copyable and not guaranteed to be mapped correctly}} expected-warning {{Type 'S3' is not trivially copyable and not guaranteed to be mapped correctly}} expected-error {{incomplete type 'S1' where a complete type is required}} +#pragma omp distribute simd reduction(+ : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 2 {{const-qualified variable cannot be reduction}} expected-error {{'operator+' is a private member of 'S2'}} expected-warning {{type 'S2' is not trivially copyable and not guaranteed to be mapped correctly}} expected-warning {{type 'S3' is not trivially copyable and not guaranteed to be mapped correctly}} expected-error {{incomplete type 'S1' where a complete type is required}} for (int i = 0; i < 10; ++i) foo(); #pragma omp target #pragma omp teams -#pragma omp distribute simd reduction(min : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 2 {{arguments of OpenMP clause 'reduction' for 'min' or 'max' must be of arithmetic type}} expected-error 2 {{const-qualified variable cannot be reduction}} expected-warning {{Type 'S2' is not trivially copyable and not guaranteed to be mapped correctly}} expected-warning {{Type 'S3' is not trivially copyable and not guaranteed to be mapped correctly}} expected-error {{incomplete type 'S1' where a complete type is required}} +#pragma omp distribute simd reduction(min : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 2 {{arguments of OpenMP clause 'reduction' for 'min' or 'max' must be of arithmetic type}} expected-error 2 {{const-qualified variable cannot be reduction}} expected-warning {{type 'S2' is not trivially copyable and not guaranteed to be mapped correctly}} expected-warning {{type 'S3' is not trivially copyable and not guaranteed to be mapped correctly}} expected-error {{incomplete type 'S1' where a complete type is required}} for (int i = 0; i < 10; ++i) foo(); #pragma omp target @@ -391,12 +391,12 @@ int main(int argc, char **argv) { foo(); #pragma omp target #pragma omp teams -#pragma omp distribute simd reduction(+ : ba) // expected-error {{const-qualified variable cannot be reduction}} expected-warning {{Type 'const S2[5]' is not trivially copyable and not guaranteed to be mapped correctly}} +#pragma omp distribute simd reduction(+ : ba) // expected-error {{const-qualified variable cannot be reduction}} expected-warning {{type 'const S2[5]' is not trivially copyable and not guaranteed to be mapped correctly}} for (int i = 0; i < 10; ++i) foo(); #pragma omp target #pragma omp teams -#pragma omp distribute simd reduction(* : ca) // expected-error {{const-qualified variable cannot be reduction}} expected-warning {{Type 'const S3[5]' is not trivially copyable and not guaranteed to be mapped correctly}} +#pragma omp distribute simd reduction(* : ca) // expected-error {{const-qualified variable cannot be reduction}} expected-warning {{type 'const S3[5]' is not trivially copyable and not guaranteed to be mapped correctly}} for (int i = 0; i < 10; ++i) foo(); #pragma omp target @@ -421,12 +421,12 @@ int main(int argc, char **argv) { foo(); #pragma omp target #pragma omp teams -#pragma omp distribute simd reduction(& : e, g) // expected-error {{calling a private constructor of class 'S4'}} expected-error {{calling a private constructor of class 'S5'}} expected-error {{invalid operands to binary expression ('S5' and 'S5')}} expected-warning {{Type 'S4' is not trivially copyable and not guaranteed to be mapped correctly}} expected-warning {{Type 'S5' is not trivially copyable and not guaranteed to be mapped correctly}}} +#pragma omp distribute simd reduction(& : e, g) // expected-error {{calling a private constructor of class 'S4'}} expected-error {{calling a private constructor of class 'S5'}} expected-error {{invalid operands to binary expression ('S5' and 'S5')}} expected-warning {{type 'S4' is not trivially copyable and not guaranteed to be mapped correctly}} expected-warning {{type 'S5' is not trivially copyable and not guaranteed to be mapped correctly}}} for (int i = 0; i < 10; ++i) foo(); #pragma omp target #pragma omp teams -#pragma omp distribute simd reduction(+ : h, k, B::x) // expected-error 2 {{threadprivate or thread local variable cannot be reduction}} expected-warning {{Type 'S3' is not trivially copyable and not guaranteed to be mapped correctly}} +#pragma omp distribute simd reduction(+ : h, k, B::x) // expected-error 2 {{threadprivate or thread local variable cannot be reduction}} expected-warning {{type 'S3' is not trivially copyable and not guaranteed to be mapped correctly}} for (int i = 0; i < 10; ++i) foo(); #pragma omp target @@ -440,7 +440,7 @@ int main(int argc, char **argv) { for (int i = 0; i < 10; ++i) foo(); #if __cplusplus < 201103L // < C++11 -// expected-warning@+5 {{Type 'S3' is not trivially copyable and not guaranteed to be mapped correctly}} +// expected-warning@+5 {{type 'S3' is not trivially copyable and not guaranteed to be mapped correctly}} #endif #pragma omp parallel private(k) #pragma omp target @@ -449,7 +449,7 @@ int main(int argc, char **argv) { for (int i = 0; i < 10; ++i) foo(); #if __cplusplus < 201103L // < C++11 -// expected-warning@+4 {{Type 'S3' is not trivially copyable and not guaranteed to be mapped correctly}} +// expected-warning@+4 {{type 'S3' is not trivially copyable and not guaranteed to be mapped correctly}} #endif #pragma omp target #pragma omp teams diff --git a/clang/test/OpenMP/reduction_implicit_map.cpp b/clang/test/OpenMP/reduction_implicit_map.cpp index 0f67cdc56ddc..765e90bcba85 100644 --- a/clang/test/OpenMP/reduction_implicit_map.cpp +++ b/clang/test/OpenMP/reduction_implicit_map.cpp @@ -47,7 +47,7 @@ int bar() { S2 o[5]; //warnig "copyable and not guaranteed to be mapped correctly" and //implicit map generated. -#pragma omp target parallel reduction(+:o[0]) //expected-warning {{Type 'S2' is not trivially copyable and not guaranteed to be mapped correctly}} +#pragma omp target parallel reduction(+:o[0]) //expected-warning {{type 'S2' is not trivially copyable and not guaranteed to be mapped correctly}} for (int i = 0; i < 10; i++); double b[10][10][10]; //no error no implicit map generated, the map for b is generated but not diff --git a/clang/test/OpenMP/requires_default_atomic_mem_order_messages.cpp b/clang/test/OpenMP/requires_default_atomic_mem_order_messages.cpp index 19f6ede043d8..5160fbbfb4a7 100644 --- a/clang/test/OpenMP/requires_default_atomic_mem_order_messages.cpp +++ b/clang/test/OpenMP/requires_default_atomic_mem_order_messages.cpp @@ -7,6 +7,6 @@ void foo2() { } #pragma omp requires atomic_default_mem_order(seq_cst) // expected-error {{'atomic' region encountered before requires directive with 'atomic_default_mem_order' clause}} expected-note 2 {{atomic_default_mem_order clause previously used here}} -#pragma omp requires atomic_default_mem_order(acq_rel) // expected-error {{'atomic' region encountered before requires directive with 'atomic_default_mem_order' clause}} expected-error {{Only one atomic_default_mem_order clause can appear on a requires directive in a single translation unit}} -#pragma omp requires atomic_default_mem_order(relaxed) // expected-error {{'atomic' region encountered before requires directive with 'atomic_default_mem_order' clause}} expected-error {{Only one atomic_default_mem_order clause can appear on a requires directive in a single translation unit}} +#pragma omp requires atomic_default_mem_order(acq_rel) // expected-error {{'atomic' region encountered before requires directive with 'atomic_default_mem_order' clause}} expected-error {{only one atomic_default_mem_order clause can appear on a requires directive in a single translation unit}} +#pragma omp requires atomic_default_mem_order(relaxed) // expected-error {{'atomic' region encountered before requires directive with 'atomic_default_mem_order' clause}} expected-error {{only one atomic_default_mem_order clause can appear on a requires directive in a single translation unit}} #pragma omp requires atomic_default_mem_order(release) // expected-error {{expected 'seq_cst', 'acq_rel' or 'relaxed' in OpenMP clause 'atomic_default_mem_order'}} expected-error {{expected at least one clause on '#pragma omp requires' directive}} diff --git a/clang/test/OpenMP/requires_messages.cpp b/clang/test/OpenMP/requires_messages.cpp index 10d311631b10..dbb2b317067b 100644 --- a/clang/test/OpenMP/requires_messages.cpp +++ b/clang/test/OpenMP/requires_messages.cpp @@ -6,39 +6,39 @@ int a; #pragma omp requires unified_shared_memory // rev-note {{unified_shared_memory clause previously used here}} expected-note{{unified_shared_memory clause previously used here}} -#pragma omp requires unified_shared_memory, unified_shared_memory // expected-error {{Only one unified_shared_memory clause can appear on a requires directive in a single translation unit}} expected-error {{directive '#pragma omp requires' cannot contain more than one 'unified_shared_memory' clause}} +#pragma omp requires unified_shared_memory, unified_shared_memory // expected-error {{only one unified_shared_memory clause can appear on a requires directive in a single translation unit}} expected-error {{directive '#pragma omp requires' cannot contain more than one 'unified_shared_memory' clause}} -#pragma omp requires unified_address // expected-error {{Only one unified_address clause can appear on a requires directive in a single translation unit}} +#pragma omp requires unified_address // expected-error {{only one unified_address clause can appear on a requires directive in a single translation unit}} -#pragma omp requires unified_address, unified_address // expected-error {{Only one unified_address clause can appear on a requires directive in a single translation unit}} expected-error {{directive '#pragma omp requires' cannot contain more than one 'unified_address' clause}} +#pragma omp requires unified_address, unified_address // expected-error {{only one unified_address clause can appear on a requires directive in a single translation unit}} expected-error {{directive '#pragma omp requires' cannot contain more than one 'unified_address' clause}} #ifdef OMP99 #pragma omp requires reverse_offload // rev-note {{reverse_offload clause previously used here}} rev-note {{reverse_offload clause previously used here}} -#pragma omp requires reverse_offload, reverse_offload // rev-error {{Only one reverse_offload clause can appear on a requires directive in a single translation unit}} rev-error {{directive '#pragma omp requires' cannot contain more than one 'reverse_offload' clause}} +#pragma omp requires reverse_offload, reverse_offload // rev-error {{only one reverse_offload clause can appear on a requires directive in a single translation unit}} rev-error {{directive '#pragma omp requires' cannot contain more than one 'reverse_offload' clause}} #endif #pragma omp requires dynamic_allocators // rev-note {{dynamic_allocators clause previously used here}} expected-note {{dynamic_allocators clause previously used here}} -#pragma omp requires dynamic_allocators, dynamic_allocators // expected-error {{Only one dynamic_allocators clause can appear on a requires directive in a single translation unit}} expected-error {{directive '#pragma omp requires' cannot contain more than one 'dynamic_allocators' clause}} +#pragma omp requires dynamic_allocators, dynamic_allocators // expected-error {{only one dynamic_allocators clause can appear on a requires directive in a single translation unit}} expected-error {{directive '#pragma omp requires' cannot contain more than one 'dynamic_allocators' clause}} #pragma omp requires atomic_default_mem_order(seq_cst) // rev-note {{atomic_default_mem_order clause previously used here}} expected-note {{atomic_default_mem_order clause previously used here}} expected-note {{atomic_default_mem_order clause previously used here}} expected-note {{atomic_default_mem_order clause previously used here}} expected-note {{atomic_default_mem_order clause previously used here}} -#pragma omp requires atomic_default_mem_order(acq_rel) // expected-error {{Only one atomic_default_mem_order clause can appear on a requires directive in a single translation unit}} +#pragma omp requires atomic_default_mem_order(acq_rel) // expected-error {{only one atomic_default_mem_order clause can appear on a requires directive in a single translation unit}} -#pragma omp requires atomic_default_mem_order(relaxed) // expected-error {{Only one atomic_default_mem_order clause can appear on a requires directive in a single translation unit}} +#pragma omp requires atomic_default_mem_order(relaxed) // expected-error {{only one atomic_default_mem_order clause can appear on a requires directive in a single translation unit}} #pragma omp requires atomic_default_mem_order // expected-error {{expected '(' after 'atomic_default_mem_order'}} expected-error {{expected at least one clause on '#pragma omp requires' directive}} #pragma omp requires atomic_default_mem_order( // expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error {{expected 'seq_cst', 'acq_rel' or 'relaxed' in OpenMP clause 'atomic_default_mem_order'}} expected-error {{expected at least one clause on '#pragma omp requires' directive}} -#pragma omp requires atomic_default_mem_order(seq_cst // expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error {{Only one atomic_default_mem_order clause can appear on a requires directive in a single translation unit}} +#pragma omp requires atomic_default_mem_order(seq_cst // expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error {{only one atomic_default_mem_order clause can appear on a requires directive in a single translation unit}} #pragma omp requires atomic_default_mem_order(invalid_modifier) // expected-error {{expected 'seq_cst', 'acq_rel' or 'relaxed' in OpenMP clause 'atomic_default_mem_order'}} expected-error {{expected at least one clause on '#pragma omp requires' directive}} #pragma omp requires atomic_default_mem_order(shared) // expected-error {{expected 'seq_cst', 'acq_rel' or 'relaxed' in OpenMP clause 'atomic_default_mem_order'}} expected-error {{expected at least one clause on '#pragma omp requires' directive}} -#pragma omp requires atomic_default_mem_order(acq_rel), atomic_default_mem_order(relaxed) // expected-error {{directive '#pragma omp requires' cannot contain more than one 'atomic_default_mem_order' claus}} expected-error {{Only one atomic_default_mem_order clause can appear on a requires directive in a single translation unit}} +#pragma omp requires atomic_default_mem_order(acq_rel), atomic_default_mem_order(relaxed) // expected-error {{directive '#pragma omp requires' cannot contain more than one 'atomic_default_mem_order' claus}} expected-error {{only one atomic_default_mem_order clause can appear on a requires directive in a single translation unit}} #pragma omp requires // expected-error {{expected at least one clause on '#pragma omp requires' directive}} @@ -46,18 +46,18 @@ int a; #pragma omp requires nowait // expected-error {{unexpected OpenMP clause 'nowait' in directive '#pragma omp requires'}} expected-error {{expected at least one clause on '#pragma omp requires' directive}} -#pragma omp requires unified_address, invalid_clause // expected-warning {{extra tokens at the end of '#pragma omp requires' are ignored}} expected-error {{Only one unified_address clause can appear on a requires directive in a single translation unit}} +#pragma omp requires unified_address, invalid_clause // expected-warning {{extra tokens at the end of '#pragma omp requires' are ignored}} expected-error {{only one unified_address clause can appear on a requires directive in a single translation unit}} #pragma omp requires invalid_clause unified_address // expected-warning {{extra tokens at the end of '#pragma omp requires' are ignored}} expected-error {{expected at least one clause on '#pragma omp requires' directive}} #ifdef OMP99 -#pragma omp requires unified_shared_memory, unified_address, reverse_offload, dynamic_allocators, atomic_default_mem_order(seq_cst) // rev-error {{Only one unified_shared_memory clause can appear on a requires directive in a single translation unit}} rev-error{{Only one unified_address clause can appear on a requires directive in a single translation unit}} rev-error{{Only one reverse_offload clause can appear on a requires directive in a single translation unit}} rev-error{{Only one dynamic_allocators clause can appear on a requires directive in a single translation unit}} rev-error {{Only one atomic_default_mem_order clause can appear on a requires directive in a single translation unit}} +#pragma omp requires unified_shared_memory, unified_address, reverse_offload, dynamic_allocators, atomic_default_mem_order(seq_cst) // rev-error {{only one unified_shared_memory clause can appear on a requires directive in a single translation unit}} rev-error{{only one unified_address clause can appear on a requires directive in a single translation unit}} rev-error{{only one reverse_offload clause can appear on a requires directive in a single translation unit}} rev-error{{only one dynamic_allocators clause can appear on a requires directive in a single translation unit}} rev-error {{only one atomic_default_mem_order clause can appear on a requires directive in a single translation unit}} #endif namespace A { - #pragma omp requires unified_address // expected-error {{Only one unified_address clause can appear on a requires directive in a single translation unit}} + #pragma omp requires unified_address // expected-error {{only one unified_address clause can appear on a requires directive in a single translation unit}} namespace B { - #pragma omp requires unified_address // expected-error {{Only one unified_address clause can appear on a requires directive in a single translation unit}} + #pragma omp requires unified_address // expected-error {{only one unified_address clause can appear on a requires directive in a single translation unit}} } } diff --git a/clang/test/OpenMP/target_device_ancestor_messages.cpp b/clang/test/OpenMP/target_device_ancestor_messages.cpp index bc1d668d1914..e6705b369c70 100644 --- a/clang/test/OpenMP/target_device_ancestor_messages.cpp +++ b/clang/test/OpenMP/target_device_ancestor_messages.cpp @@ -2,6 +2,6 @@ // RUN: %clang_cc1 -triple=x86_64 -verify -fopenmp-simd -fopenmp-targets=x86_64 -x c++ -fexceptions -fcxx-exceptions %s void bar() { -#pragma omp target device(ancestor : 1) // expected-error {{Device clause with ancestor device-modifier used without specifying 'requires reverse_offload'}} +#pragma omp target device(ancestor : 1) // expected-error {{device clause with ancestor device-modifier used without specifying 'requires reverse_offload'}} ; } diff --git a/clang/test/OpenMP/target_firstprivate_messages.cpp b/clang/test/OpenMP/target_firstprivate_messages.cpp index 9b211297f531..2eafb367c0c4 100644 --- a/clang/test/OpenMP/target_firstprivate_messages.cpp +++ b/clang/test/OpenMP/target_firstprivate_messages.cpp @@ -56,7 +56,7 @@ public: S5(int v) : a(v) {} S5 &operator=(S5 &s) { #pragma omp target firstprivate(a) firstprivate(this->a) firstprivate(s.a) // expected-error {{expected variable name or data member of current class}} - for (int k = 0; k < s.a; ++k) // expected-warning {{Type 'S5' is not trivially copyable and not guaranteed to be mapped correctly}} + for (int k = 0; k < s.a; ++k) // expected-warning {{type 'S5' is not trivially copyable and not guaranteed to be mapped correctly}} ++s.a; return *this; } diff --git a/clang/test/OpenMP/target_map_messages.cpp b/clang/test/OpenMP/target_map_messages.cpp index 3bd432b47e63..10f46687d637 100644 --- a/clang/test/OpenMP/target_map_messages.cpp +++ b/clang/test/OpenMP/target_map_messages.cpp @@ -681,13 +681,13 @@ T tmain(T argc) { #pragma omp target data map(tofrom: argc > 0 ? x : y) // lt50-error 2 {{expected expression containing only member accesses and/or array sections based on named variables}} ge50-error 2 {{expected addressable lvalue in 'map' clause}} #pragma omp target data map(argc) #pragma omp target data map(S1) // expected-error {{'S1' does not refer to a value}} -#pragma omp target data map(a, b, c, d, f) // expected-error {{incomplete type 'S1' where a complete type is required}} warn-warning 2 {{Type 'const S2' is not trivially copyable and not guaranteed to be mapped correctly}} warn-warning 2 {{Type 'const S3' is not trivially copyable and not guaranteed to be mapped correctly}} -#pragma omp target data map(ba) // warn-warning 2 {{Type 'const S2 [5]' is not trivially copyable and not guaranteed to be mapped correctly}} -#pragma omp target data map(ca) // warn-warning 2 {{Type 'const S3 [5]' is not trivially copyable and not guaranteed to be mapped correctly}} +#pragma omp target data map(a, b, c, d, f) // expected-error {{incomplete type 'S1' where a complete type is required}} warn-warning 2 {{type 'const S2' is not trivially copyable and not guaranteed to be mapped correctly}} warn-warning 2 {{type 'const S3' is not trivially copyable and not guaranteed to be mapped correctly}} +#pragma omp target data map(ba) // warn-warning 2 {{type 'const S2 [5]' is not trivially copyable and not guaranteed to be mapped correctly}} +#pragma omp target data map(ca) // warn-warning 2 {{type 'const S3 [5]' is not trivially copyable and not guaranteed to be mapped correctly}} #pragma omp target data map(da) #pragma omp target data map(S2::S2s) #pragma omp target data map(S2::S2sc) -#pragma omp target data map(e, g) // warn-warning 2 {{Type 'S4' is not trivially copyable and not guaranteed to be mapped correctly}} warn-warning 2 {{Type 'S5' is not trivially copyable and not guaranteed to be mapped correctly}} +#pragma omp target data map(e, g) // warn-warning 2 {{type 'S4' is not trivially copyable and not guaranteed to be mapped correctly}} warn-warning 2 {{type 'S5' is not trivially copyable and not guaranteed to be mapped correctly}} #pragma omp target data map(h) // expected-error {{threadprivate variables are not allowed in 'map' clause}} #pragma omp target data map(k) map(k) // lt50-error 2 {{variable already marked as mapped in current construct}} lt50-note 2 {{used here}} #pragma omp target map(k), map(k[:5]) // lt50-error 2 {{pointer cannot be mapped along with a section derived from itself}} lt50-note 2 {{used here}} @@ -815,14 +815,14 @@ int main(int argc, char **argv) { #pragma omp target data map(tofrom: argc > 0 ? argv[1] : argv[2]) // lt50-error {{expected expression containing only member accesses and/or array sections based on named variables}} ge50-error {{expected addressable lvalue in 'map' clause}} #pragma omp target data map(argc) #pragma omp target data map(S1) // expected-error {{'S1' does not refer to a value}} -#pragma omp target data map(a, b, c, d, f) // expected-error {{incomplete type 'S1' where a complete type is required}} warn-warning {{Type 'const S2' is not trivially copyable and not guaranteed to be mapped correctly}} warn-warning {{Type 'const S3' is not trivially copyable and not guaranteed to be mapped correctly}} +#pragma omp target data map(a, b, c, d, f) // expected-error {{incomplete type 'S1' where a complete type is required}} warn-warning {{type 'const S2' is not trivially copyable and not guaranteed to be mapped correctly}} warn-warning {{type 'const S3' is not trivially copyable and not guaranteed to be mapped correctly}} #pragma omp target data map(argv[1]) -#pragma omp target data map(ba) // warn-warning {{Type 'const S2 [5]' is not trivially copyable and not guaranteed to be mapped correctly}} -#pragma omp target data map(ca) // warn-warning {{Type 'const S3 [5]' is not trivially copyable and not guaranteed to be mapped correctly}} +#pragma omp target data map(ba) // warn-warning {{type 'const S2 [5]' is not trivially copyable and not guaranteed to be mapped correctly}} +#pragma omp target data map(ca) // warn-warning {{type 'const S3 [5]' is not trivially copyable and not guaranteed to be mapped correctly}} #pragma omp target data map(da) #pragma omp target data map(S2::S2s) #pragma omp target data map(S2::S2sc) -#pragma omp target data map(e, g) // warn-warning {{Type 'S4' is not trivially copyable and not guaranteed to be mapped correctly}} warn-warning {{Type 'S5' is not trivially copyable and not guaranteed to be mapped correctly}} +#pragma omp target data map(e, g) // warn-warning {{type 'S4' is not trivially copyable and not guaranteed to be mapped correctly}} warn-warning {{type 'S5' is not trivially copyable and not guaranteed to be mapped correctly}} #pragma omp target data map(h) // expected-error {{threadprivate variables are not allowed in 'map' clause}} #pragma omp target data map(k), map(k) // lt50-error {{variable already marked as mapped in current construct}} lt50-note {{used here}} #pragma omp target map(k), map(k[:5]) // lt50-error {{pointer cannot be mapped along with a section derived from itself}} lt50-note {{used here}} @@ -872,7 +872,7 @@ int main(int argc, char **argv) { {} #pragma omp target firstprivate(j) map(j) // expected-error {{firstprivate variable cannot be in a map clause in '#pragma omp target' directive}} expected-note {{defined as firstprivate}} {} -#pragma omp target map(m) // warn-warning {{Type 'S6' is not trivially copyable and not guaranteed to be mapped correctly}} +#pragma omp target map(m) // warn-warning {{type 'S6' is not trivially copyable and not guaranteed to be mapped correctly}} {} #pragma omp target { s.a++; } @@ -920,7 +920,7 @@ int main(int argc, char **argv) { { s.a++; } #pragma omp target map(s.s.s.b[:2]) { s.s.s.b[0]++; } -#pragma omp target map(s8[0:1], s9) // warn-warning {{Type 'class S8' is not trivially copyable and not guaranteed to be mapped correctly}} warn-warning {{Type 'class S9' is not trivially copyable and not guaranteed to be mapped correctly}} +#pragma omp target map(s8[0:1], s9) // warn-warning {{type 'class S8' is not trivially copyable and not guaranteed to be mapped correctly}} warn-warning {{type 'class S9' is not trivially copyable and not guaranteed to be mapped correctly}} {} int **BB, *offset, *a; diff --git a/clang/test/OpenMP/target_parallel_for_private_messages.cpp b/clang/test/OpenMP/target_parallel_for_private_messages.cpp index 1c31badf51cd..81b4be4923d7 100644 --- a/clang/test/OpenMP/target_parallel_for_private_messages.cpp +++ b/clang/test/OpenMP/target_parallel_for_private_messages.cpp @@ -56,7 +56,7 @@ public: S5(int v) : a(v) {} S5 &operator=(S5 &s) { #pragma omp target parallel for private(a) private(this->a) private(s.a) // expected-error {{expected variable name or data member of current class}} - for (int k = 0; k < s.a; ++k) // expected-warning {{Type 'S5' is not trivially copyable and not guaranteed to be mapped correctly}} + for (int k = 0; k < s.a; ++k) // expected-warning {{type 'S5' is not trivially copyable and not guaranteed to be mapped correctly}} ++s.a; return *this; } diff --git a/clang/test/OpenMP/target_parallel_for_simd_private_messages.cpp b/clang/test/OpenMP/target_parallel_for_simd_private_messages.cpp index db9d495698b0..c9b5bac0e693 100644 --- a/clang/test/OpenMP/target_parallel_for_simd_private_messages.cpp +++ b/clang/test/OpenMP/target_parallel_for_simd_private_messages.cpp @@ -56,7 +56,7 @@ public: S5(int v) : a(v) {} S5 &operator=(S5 &s) { #pragma omp target parallel for simd private(a) private(this->a) private(s.a) // expected-error {{expected variable name or data member of current class}} - for (int k = 0; k < s.a; ++k) // expected-warning {{Type 'S5' is not trivially copyable and not guaranteed to be mapped correctly}} + for (int k = 0; k < s.a; ++k) // expected-warning {{type 'S5' is not trivially copyable and not guaranteed to be mapped correctly}} ++s.a; return *this; } diff --git a/clang/test/OpenMP/target_private_messages.cpp b/clang/test/OpenMP/target_private_messages.cpp index 7ee0c8cffb9c..8cdd3a11e87a 100644 --- a/clang/test/OpenMP/target_private_messages.cpp +++ b/clang/test/OpenMP/target_private_messages.cpp @@ -50,7 +50,7 @@ public: S5(int v) : a(v) {} S5 &operator=(S5 &s) { #pragma omp target private(a) private(this->a) private(s.a) // expected-error {{expected variable name or data member of current class}} - for (int k = 0; k < s.a; ++k) // expected-warning {{Type 'S5' is not trivially copyable and not guaranteed to be mapped correctly}} + for (int k = 0; k < s.a; ++k) // expected-warning {{type 'S5' is not trivially copyable and not guaranteed to be mapped correctly}} ++s.a; return *this; } diff --git a/clang/test/OpenMP/target_simd_private_messages.cpp b/clang/test/OpenMP/target_simd_private_messages.cpp index 4a55a506d4ab..f6e4e714f8ff 100644 --- a/clang/test/OpenMP/target_simd_private_messages.cpp +++ b/clang/test/OpenMP/target_simd_private_messages.cpp @@ -56,7 +56,7 @@ public: S5(int v) : a(v) {} S5 &operator=(S5 &s) { #pragma omp target simd private(a) private(this->a) private(s.a) // expected-error {{expected variable name or data member of current class}} - for (int k = 0; k < s.a; ++k) // expected-warning {{Type 'S5' is not trivially copyable and not guaranteed to be mapped correctly}} + for (int k = 0; k < s.a; ++k) // expected-warning {{type 'S5' is not trivially copyable and not guaranteed to be mapped correctly}} ++s.a; return *this; } diff --git a/clang/test/OpenMP/target_teams_distribute_firstprivate_messages.cpp b/clang/test/OpenMP/target_teams_distribute_firstprivate_messages.cpp index fccf5515998d..195af52b7892 100644 --- a/clang/test/OpenMP/target_teams_distribute_firstprivate_messages.cpp +++ b/clang/test/OpenMP/target_teams_distribute_firstprivate_messages.cpp @@ -119,7 +119,7 @@ int main(int argc, char **argv) { for (i = 0; i < argc; ++i) foo(); #pragma omp target -#pragma omp teams distribute firstprivate(ca) // expected-error {{no matching constructor for initialization of 'S3'}} expected-warning {{Type 'const S3[5]' is not trivially copyable and not guaranteed to be mapped correctly}} +#pragma omp teams distribute firstprivate(ca) // expected-error {{no matching constructor for initialization of 'S3'}} expected-warning {{type 'const S3[5]' is not trivially copyable and not guaranteed to be mapped correctly}} for (i = 0; i < argc; ++i) foo(); #pragma omp target teams distribute firstprivate(da, z) diff --git a/clang/test/OpenMP/teams_distribute_loop_messages.cpp b/clang/test/OpenMP/teams_distribute_loop_messages.cpp index 167f653e2cd7..e5f146679e5f 100644 --- a/clang/test/OpenMP/teams_distribute_loop_messages.cpp +++ b/clang/test/OpenMP/teams_distribute_loop_messages.cpp @@ -416,7 +416,7 @@ int test_with_random_access_iterator() { Iter0 begin0, end0; #pragma omp target #pragma omp teams distribute - for (GoodIter I = begin; I < end; ++I) // expected-warning 2 {{Type 'GoodIter' is not trivially copyable and not guaranteed to be mapped correctly}} + for (GoodIter I = begin; I < end; ++I) // expected-warning 2 {{type 'GoodIter' is not trivially copyable and not guaranteed to be mapped correctly}} ++I; #pragma omp target #pragma omp teams distribute @@ -425,31 +425,31 @@ int test_with_random_access_iterator() { ++I; #pragma omp target #pragma omp teams distribute - for (GoodIter I = begin; I >= end; --I) // expected-warning 2 {{Type 'GoodIter' is not trivially copyable and not guaranteed to be mapped correctly}} + for (GoodIter I = begin; I >= end; --I) // expected-warning 2 {{type 'GoodIter' is not trivially copyable and not guaranteed to be mapped correctly}} ++I; #pragma omp target #pragma omp teams distribute // expected-warning@+1 {{initialization clause of OpenMP for loop is not in canonical form ('var = init' or 'T var = init')}} - for (GoodIter I(begin); I < end; ++I) // expected-warning 2 {{Type 'GoodIter' is not trivially copyable and not guaranteed to be mapped correctly}} + for (GoodIter I(begin); I < end; ++I) // expected-warning 2 {{type 'GoodIter' is not trivially copyable and not guaranteed to be mapped correctly}} ++I; #pragma omp target #pragma omp teams distribute // expected-warning@+1 {{initialization clause of OpenMP for loop is not in canonical form ('var = init' or 'T var = init')}} - for (GoodIter I(nullptr); I < end; ++I) // expected-warning {{Type 'GoodIter' is not trivially copyable and not guaranteed to be mapped correctly}} + for (GoodIter I(nullptr); I < end; ++I) // expected-warning {{type 'GoodIter' is not trivially copyable and not guaranteed to be mapped correctly}} ++I; #pragma omp target #pragma omp teams distribute // expected-warning@+1 {{initialization clause of OpenMP for loop is not in canonical form ('var = init' or 'T var = init')}} - for (GoodIter I(0); I < end; ++I) // expected-warning {{Type 'GoodIter' is not trivially copyable and not guaranteed to be mapped correctly}} + for (GoodIter I(0); I < end; ++I) // expected-warning {{type 'GoodIter' is not trivially copyable and not guaranteed to be mapped correctly}} ++I; #pragma omp target #pragma omp teams distribute // expected-warning@+1 {{initialization clause of OpenMP for loop is not in canonical form ('var = init' or 'T var = init')}} - for (GoodIter I(1, 2); I < end; ++I) // expected-warning {{Type 'GoodIter' is not trivially copyable and not guaranteed to be mapped correctly}} + for (GoodIter I(1, 2); I < end; ++I) // expected-warning {{type 'GoodIter' is not trivially copyable and not guaranteed to be mapped correctly}} ++I; #pragma omp target #pragma omp teams distribute - for (begin = GoodIter(0); begin < end; ++begin) // expected-warning {{Type 'GoodIter' is not trivially copyable and not guaranteed to be mapped correctly}} + for (begin = GoodIter(0); begin < end; ++begin) // expected-warning {{type 'GoodIter' is not trivially copyable and not guaranteed to be mapped correctly}} ++begin; #pragma omp target #pragma omp teams distribute @@ -464,7 +464,7 @@ int test_with_random_access_iterator() { ++begin; #pragma omp target #pragma omp teams distribute - for (begin = end; begin < end; ++begin) // expected-warning {{Type 'GoodIter' is not trivially copyable and not guaranteed to be mapped correctly}} + for (begin = end; begin < end; ++begin) // expected-warning {{type 'GoodIter' is not trivially copyable and not guaranteed to be mapped correctly}} ++begin; #pragma omp target #pragma omp teams distribute @@ -489,7 +489,7 @@ int test_with_random_access_iterator() { ++I; #pragma omp target #pragma omp teams distribute - for (GoodIter I = begin; I >= end; I = I - 1) // expected-warning 2 {{Type 'GoodIter' is not trivially copyable and not guaranteed to be mapped correctly}} + for (GoodIter I = begin; I >= end; I = I - 1) // expected-warning 2 {{type 'GoodIter' is not trivially copyable and not guaranteed to be mapped correctly}} ++I; #pragma omp target #pragma omp teams distribute @@ -551,19 +551,19 @@ public: #pragma omp teams distribute // expected-note@+2 {{loop step is expected to be positive due to this condition}} // expected-error@+1 {{increment expression must cause 'I' to increase on each iteration of OpenMP for loop}} - for (IT I = begin; I < end; I = I + ST) { // expected-warning 2 {{Type 'GoodIter' is not trivially copyable and not guaranteed to be mapped correctly}} + for (IT I = begin; I < end; I = I + ST) { // expected-warning 2 {{type 'GoodIter' is not trivially copyable and not guaranteed to be mapped correctly}} ++I; } #pragma omp target #pragma omp teams distribute // expected-note@+2 {{loop step is expected to be positive due to this condition}} // expected-error@+1 {{increment expression must cause 'I' to increase on each iteration of OpenMP for loop}} - for (IT I = begin; I <= end; I += ST) { // expected-warning 2 {{Type 'GoodIter' is not trivially copyable and not guaranteed to be mapped correctly}} + for (IT I = begin; I <= end; I += ST) { // expected-warning 2 {{type 'GoodIter' is not trivially copyable and not guaranteed to be mapped correctly}} ++I; } #pragma omp target #pragma omp teams distribute - for (IT I = begin; I < end; ++I) { // expected-warning 4 {{Type 'GoodIter' is not trivially copyable and not guaranteed to be mapped correctly}} + for (IT I = begin; I < end; ++I) { // expected-warning 4 {{type 'GoodIter' is not trivially copyable and not guaranteed to be mapped correctly}} ++I; } } @@ -599,7 +599,7 @@ int dotest_gt(IT begin, IT end) { #pragma omp target #pragma omp teams distribute - for (IT I = begin; I < end; I += TC::step()) { // expected-warning 2 {{Type 'GoodIter' is not trivially copyable and not guaranteed to be mapped correctly}} + for (IT I = begin; I < end; I += TC::step()) { // expected-warning 2 {{type 'GoodIter' is not trivially copyable and not guaranteed to be mapped correctly}} ++I; } } @@ -702,7 +702,7 @@ void test_loop_firstprivate_lastprivate() { S s(4); // expected-error@+2 {{lastprivate variable cannot be firstprivate}} expected-note@+2 {{defined as lastprivate}} #pragma omp target -#pragma omp teams distribute lastprivate(s) firstprivate(s) // expected-error {{calling a private constructor of class 'S'}} expected-warning {{Type 'S' is not trivially copyable and not guaranteed to be mapped correctly}} +#pragma omp teams distribute lastprivate(s) firstprivate(s) // expected-error {{calling a private constructor of class 'S'}} expected-warning {{type 'S' is not trivially copyable and not guaranteed to be mapped correctly}} for (int i = 0; i < 16; ++i) ; } diff --git a/clang/test/OpenMP/teams_distribute_parallel_for_loop_messages.cpp b/clang/test/OpenMP/teams_distribute_parallel_for_loop_messages.cpp index cdfc5eaec228..67e3ce4dc157 100644 --- a/clang/test/OpenMP/teams_distribute_parallel_for_loop_messages.cpp +++ b/clang/test/OpenMP/teams_distribute_parallel_for_loop_messages.cpp @@ -414,7 +414,7 @@ int test_with_random_access_iterator() { Iter0 begin0, end0; #pragma omp target #pragma omp teams distribute parallel for - for (GoodIter I = begin; I < end; ++I) // expected-warning 2 {{Type 'GoodIter' is not trivially copyable and not guaranteed to be mapped correctly}} + for (GoodIter I = begin; I < end; ++I) // expected-warning 2 {{type 'GoodIter' is not trivially copyable and not guaranteed to be mapped correctly}} ++I; #pragma omp target #pragma omp teams distribute parallel for @@ -423,31 +423,31 @@ int test_with_random_access_iterator() { ++I; #pragma omp target #pragma omp teams distribute parallel for - for (GoodIter I = begin; I >= end; --I) // expected-warning 2 {{Type 'GoodIter' is not trivially copyable and not guaranteed to be mapped correctly}} + for (GoodIter I = begin; I >= end; --I) // expected-warning 2 {{type 'GoodIter' is not trivially copyable and not guaranteed to be mapped correctly}} ++I; #pragma omp target #pragma omp teams distribute parallel for // expected-warning@+1 {{initialization clause of OpenMP for loop is not in canonical form ('var = init' or 'T var = init')}} - for (GoodIter I(begin); I < end; ++I) // expected-warning 2 {{Type 'GoodIter' is not trivially copyable and not guaranteed to be mapped correctly}} + for (GoodIter I(begin); I < end; ++I) // expected-warning 2 {{type 'GoodIter' is not trivially copyable and not guaranteed to be mapped correctly}} ++I; #pragma omp target #pragma omp teams distribute parallel for // expected-warning@+1 {{initialization clause of OpenMP for loop is not in canonical form ('var = init' or 'T var = init')}} - for (GoodIter I(nullptr); I < end; ++I) // expected-warning {{Type 'GoodIter' is not trivially copyable and not guaranteed to be mapped correctly}} + for (GoodIter I(nullptr); I < end; ++I) // expected-warning {{type 'GoodIter' is not trivially copyable and not guaranteed to be mapped correctly}} ++I; #pragma omp target #pragma omp teams distribute parallel for // expected-warning@+1 {{initialization clause of OpenMP for loop is not in canonical form ('var = init' or 'T var = init')}} - for (GoodIter I(0); I < end; ++I) // expected-warning {{Type 'GoodIter' is not trivially copyable and not guaranteed to be mapped correctly}} + for (GoodIter I(0); I < end; ++I) // expected-warning {{type 'GoodIter' is not trivially copyable and not guaranteed to be mapped correctly}} ++I; #pragma omp target #pragma omp teams distribute parallel for // expected-warning@+1 {{initialization clause of OpenMP for loop is not in canonical form ('var = init' or 'T var = init')}} - for (GoodIter I(1, 2); I < end; ++I) // expected-warning {{Type 'GoodIter' is not trivially copyable and not guaranteed to be mapped correctly}} + for (GoodIter I(1, 2); I < end; ++I) // expected-warning {{type 'GoodIter' is not trivially copyable and not guaranteed to be mapped correctly}} ++I; #pragma omp target #pragma omp teams distribute parallel for - for (begin = GoodIter(0); begin < end; ++begin) // expected-warning {{Type 'GoodIter' is not trivially copyable and not guaranteed to be mapped correctly}} + for (begin = GoodIter(0); begin < end; ++begin) // expected-warning {{type 'GoodIter' is not trivially copyable and not guaranteed to be mapped correctly}} ++begin; #pragma omp target #pragma omp teams distribute parallel for @@ -462,7 +462,7 @@ int test_with_random_access_iterator() { ++begin; #pragma omp target #pragma omp teams distribute parallel for - for (begin = end; begin < end; ++begin) // expected-warning {{Type 'GoodIter' is not trivially copyable and not guaranteed to be mapped correctly}} + for (begin = end; begin < end; ++begin) // expected-warning {{type 'GoodIter' is not trivially copyable and not guaranteed to be mapped correctly}} ++begin; #pragma omp target #pragma omp teams distribute parallel for @@ -487,7 +487,7 @@ int test_with_random_access_iterator() { ++I; #pragma omp target #pragma omp teams distribute parallel for - for (GoodIter I = begin; I >= end; I = I - 1) // expected-warning 2 {{Type 'GoodIter' is not trivially copyable and not guaranteed to be mapped correctly}} + for (GoodIter I = begin; I >= end; I = I - 1) // expected-warning 2 {{type 'GoodIter' is not trivially copyable and not guaranteed to be mapped correctly}} ++I; #pragma omp target #pragma omp teams distribute parallel for @@ -549,19 +549,19 @@ public: #pragma omp teams distribute parallel for // expected-note@+2 {{loop step is expected to be positive due to this condition}} // expected-error@+1 {{increment expression must cause 'I' to increase on each iteration of OpenMP for loop}} - for (IT I = begin; I < end; I = I + ST) { // expected-warning 2 {{Type 'GoodIter' is not trivially copyable and not guaranteed to be mapped correctly}} + for (IT I = begin; I < end; I = I + ST) { // expected-warning 2 {{type 'GoodIter' is not trivially copyable and not guaranteed to be mapped correctly}} ++I; } #pragma omp target #pragma omp teams distribute parallel for // expected-note@+2 {{loop step is expected to be positive due to this condition}} // expected-error@+1 {{increment expression must cause 'I' to increase on each iteration of OpenMP for loop}} - for (IT I = begin; I <= end; I += ST) { // expected-warning 2 {{Type 'GoodIter' is not trivially copyable and not guaranteed to be mapped correctly}} + for (IT I = begin; I <= end; I += ST) { // expected-warning 2 {{type 'GoodIter' is not trivially copyable and not guaranteed to be mapped correctly}} ++I; } #pragma omp target #pragma omp teams distribute parallel for - for (IT I = begin; I < end; ++I) { // expected-warning 4 {{Type 'GoodIter' is not trivially copyable and not guaranteed to be mapped correctly}} + for (IT I = begin; I < end; ++I) { // expected-warning 4 {{type 'GoodIter' is not trivially copyable and not guaranteed to be mapped correctly}} ++I; } } @@ -597,7 +597,7 @@ int dotest_gt(IT begin, IT end) { #pragma omp target #pragma omp teams distribute parallel for - for (IT I = begin; I < end; I += TC::step()) { // expected-warning 2 {{Type 'GoodIter' is not trivially copyable and not guaranteed to be mapped correctly}} + for (IT I = begin; I < end; I += TC::step()) { // expected-warning 2 {{type 'GoodIter' is not trivially copyable and not guaranteed to be mapped correctly}} ++I; } } @@ -697,7 +697,7 @@ void test_loop_firstprivate_lastprivate() { S s(4); // expected-error@+2 {{lastprivate variable cannot be firstprivate}} expected-note@+2 {{defined as lastprivate}} #pragma omp target -#pragma omp teams distribute parallel for lastprivate(s) firstprivate(s) // expected-error {{calling a private constructor of class 'S'}} expected-warning {{Type 'S' is not trivially copyable and not guaranteed to be mapped correctly}} +#pragma omp teams distribute parallel for lastprivate(s) firstprivate(s) // expected-error {{calling a private constructor of class 'S'}} expected-warning {{type 'S' is not trivially copyable and not guaranteed to be mapped correctly}} for (int i = 0; i < 16; ++i) ; } diff --git a/clang/test/OpenMP/teams_distribute_parallel_for_simd_loop_messages.cpp b/clang/test/OpenMP/teams_distribute_parallel_for_simd_loop_messages.cpp index 645035a3a163..7ee8b9c9d367 100644 --- a/clang/test/OpenMP/teams_distribute_parallel_for_simd_loop_messages.cpp +++ b/clang/test/OpenMP/teams_distribute_parallel_for_simd_loop_messages.cpp @@ -416,7 +416,7 @@ int test_with_random_access_iterator() { Iter0 begin0, end0; #pragma omp target #pragma omp teams distribute parallel for simd - for (GoodIter I = begin; I < end; ++I) // expected-warning 2 {{Type 'GoodIter' is not trivially copyable and not guaranteed to be mapped correctly}} + for (GoodIter I = begin; I < end; ++I) // expected-warning 2 {{type 'GoodIter' is not trivially copyable and not guaranteed to be mapped correctly}} ++I; #pragma omp target #pragma omp teams distribute parallel for simd @@ -425,31 +425,31 @@ int test_with_random_access_iterator() { ++I; #pragma omp target #pragma omp teams distribute parallel for simd - for (GoodIter I = begin; I >= end; --I) // expected-warning 2 {{Type 'GoodIter' is not trivially copyable and not guaranteed to be mapped correctly}} + for (GoodIter I = begin; I >= end; --I) // expected-warning 2 {{type 'GoodIter' is not trivially copyable and not guaranteed to be mapped correctly}} ++I; #pragma omp target #pragma omp teams distribute parallel for simd // expected-warning@+1 {{initialization clause of OpenMP for loop is not in canonical form ('var = init' or 'T var = init')}} - for (GoodIter I(begin); I < end; ++I) // expected-warning 2 {{Type 'GoodIter' is not trivially copyable and not guaranteed to be mapped correctly}} + for (GoodIter I(begin); I < end; ++I) // expected-warning 2 {{type 'GoodIter' is not trivially copyable and not guaranteed to be mapped correctly}} ++I; #pragma omp target #pragma omp teams distribute parallel for simd // expected-warning@+1 {{initialization clause of OpenMP for loop is not in canonical form ('var = init' or 'T var = init')}} - for (GoodIter I(nullptr); I < end; ++I) // expected-warning {{Type 'GoodIter' is not trivially copyable and not guaranteed to be mapped correctly}} + for (GoodIter I(nullptr); I < end; ++I) // expected-warning {{type 'GoodIter' is not trivially copyable and not guaranteed to be mapped correctly}} ++I; #pragma omp target #pragma omp teams distribute parallel for simd // expected-warning@+1 {{initialization clause of OpenMP for loop is not in canonical form ('var = init' or 'T var = init')}} - for (GoodIter I(0); I < end; ++I) // expected-warning {{Type 'GoodIter' is not trivially copyable and not guaranteed to be mapped correctly}} + for (GoodIter I(0); I < end; ++I) // expected-warning {{type 'GoodIter' is not trivially copyable and not guaranteed to be mapped correctly}} ++I; #pragma omp target #pragma omp teams distribute parallel for simd // expected-warning@+1 {{initialization clause of OpenMP for loop is not in canonical form ('var = init' or 'T var = init')}} - for (GoodIter I(1, 2); I < end; ++I) // expected-warning {{Type 'GoodIter' is not trivially copyable and not guaranteed to be mapped correctly}} + for (GoodIter I(1, 2); I < end; ++I) // expected-warning {{type 'GoodIter' is not trivially copyable and not guaranteed to be mapped correctly}} ++I; #pragma omp target #pragma omp teams distribute parallel for simd - for (begin = GoodIter(0); begin < end; ++begin) // expected-warning 2 {{Type 'GoodIter' is not trivially copyable and not guaranteed to be mapped correctly}} + for (begin = GoodIter(0); begin < end; ++begin) // expected-warning 2 {{type 'GoodIter' is not trivially copyable and not guaranteed to be mapped correctly}} ++begin; #pragma omp target #pragma omp teams distribute parallel for simd @@ -464,7 +464,7 @@ int test_with_random_access_iterator() { ++begin; #pragma omp target #pragma omp teams distribute parallel for simd - for (begin = end; begin < end; ++begin) // expected-warning 2 {{Type 'GoodIter' is not trivially copyable and not guaranteed to be mapped correctly}} + for (begin = end; begin < end; ++begin) // expected-warning 2 {{type 'GoodIter' is not trivially copyable and not guaranteed to be mapped correctly}} ++begin; #pragma omp target #pragma omp teams distribute parallel for simd @@ -489,7 +489,7 @@ int test_with_random_access_iterator() { ++I; #pragma omp target #pragma omp teams distribute parallel for simd - for (GoodIter I = begin; I >= end; I = I - 1) // expected-warning 2 {{Type 'GoodIter' is not trivially copyable and not guaranteed to be mapped correctly}} + for (GoodIter I = begin; I >= end; I = I - 1) // expected-warning 2 {{type 'GoodIter' is not trivially copyable and not guaranteed to be mapped correctly}} ++I; #pragma omp target #pragma omp teams distribute parallel for simd @@ -551,19 +551,19 @@ public: #pragma omp teams distribute parallel for simd // expected-note@+2 {{loop step is expected to be positive due to this condition}} // expected-error@+1 {{increment expression must cause 'I' to increase on each iteration of OpenMP for loop}} - for (IT I = begin; I < end; I = I + ST) { // expected-warning 2 {{Type 'GoodIter' is not trivially copyable and not guaranteed to be mapped correctly}} + for (IT I = begin; I < end; I = I + ST) { // expected-warning 2 {{type 'GoodIter' is not trivially copyable and not guaranteed to be mapped correctly}} ++I; } #pragma omp target #pragma omp teams distribute parallel for simd // expected-note@+2 {{loop step is expected to be positive due to this condition}} // expected-error@+1 {{increment expression must cause 'I' to increase on each iteration of OpenMP for loop}} - for (IT I = begin; I <= end; I += ST) { // expected-warning 2 {{Type 'GoodIter' is not trivially copyable and not guaranteed to be mapped correctly}} + for (IT I = begin; I <= end; I += ST) { // expected-warning 2 {{type 'GoodIter' is not trivially copyable and not guaranteed to be mapped correctly}} ++I; } #pragma omp target #pragma omp teams distribute parallel for simd - for (IT I = begin; I < end; ++I) { // expected-warning 4 {{Type 'GoodIter' is not trivially copyable and not guaranteed to be mapped correctly}} + for (IT I = begin; I < end; ++I) { // expected-warning 4 {{type 'GoodIter' is not trivially copyable and not guaranteed to be mapped correctly}} ++I; } } @@ -599,7 +599,7 @@ int dotest_gt(IT begin, IT end) { #pragma omp target #pragma omp teams distribute parallel for simd - for (IT I = begin; I < end; I += TC::step()) { // expected-warning 2 {{Type 'GoodIter' is not trivially copyable and not guaranteed to be mapped correctly}} + for (IT I = begin; I < end; I += TC::step()) { // expected-warning 2 {{type 'GoodIter' is not trivially copyable and not guaranteed to be mapped correctly}} ++I; } } @@ -699,7 +699,7 @@ void test_loop_firstprivate_lastprivate() { S s(4); // expected-error@+2 {{lastprivate variable cannot be firstprivate}} expected-note@+2 {{defined as lastprivate}} #pragma omp target -#pragma omp teams distribute parallel for simd lastprivate(s) firstprivate(s) // expected-error {{calling a private constructor of class 'S'}} expected-warning {{Type 'S' is not trivially copyable and not guaranteed to be mapped correctly}} +#pragma omp teams distribute parallel for simd lastprivate(s) firstprivate(s) // expected-error {{calling a private constructor of class 'S'}} expected-warning {{type 'S' is not trivially copyable and not guaranteed to be mapped correctly}} for (int i = 0; i < 16; ++i) ; } diff --git a/clang/test/OpenMP/teams_distribute_simd_loop_messages.cpp b/clang/test/OpenMP/teams_distribute_simd_loop_messages.cpp index 13eef6a98b3d..8bfddbf6e9ee 100644 --- a/clang/test/OpenMP/teams_distribute_simd_loop_messages.cpp +++ b/clang/test/OpenMP/teams_distribute_simd_loop_messages.cpp @@ -416,7 +416,7 @@ int test_with_random_access_iterator() { Iter0 begin0, end0; #pragma omp target #pragma omp teams distribute simd - for (GoodIter I = begin; I < end; ++I) // expected-warning 2 {{Type 'GoodIter' is not trivially copyable and not guaranteed to be mapped correctly}} + for (GoodIter I = begin; I < end; ++I) // expected-warning 2 {{type 'GoodIter' is not trivially copyable and not guaranteed to be mapped correctly}} ++I; #pragma omp target #pragma omp teams distribute simd @@ -425,31 +425,31 @@ int test_with_random_access_iterator() { ++I; #pragma omp target #pragma omp teams distribute simd - for (GoodIter I = begin; I >= end; --I) // expected-warning 2 {{Type 'GoodIter' is not trivially copyable and not guaranteed to be mapped correctly}} + for (GoodIter I = begin; I >= end; --I) // expected-warning 2 {{type 'GoodIter' is not trivially copyable and not guaranteed to be mapped correctly}} ++I; #pragma omp target #pragma omp teams distribute simd // expected-warning@+1 {{initialization clause of OpenMP for loop is not in canonical form ('var = init' or 'T var = init')}} - for (GoodIter I(begin); I < end; ++I) // expected-warning 2 {{Type 'GoodIter' is not trivially copyable and not guaranteed to be mapped correctly}} + for (GoodIter I(begin); I < end; ++I) // expected-warning 2 {{type 'GoodIter' is not trivially copyable and not guaranteed to be mapped correctly}} ++I; #pragma omp target #pragma omp teams distribute simd // expected-warning@+1 {{initialization clause of OpenMP for loop is not in canonical form ('var = init' or 'T var = init')}} - for (GoodIter I(nullptr); I < end; ++I) // expected-warning {{Type 'GoodIter' is not trivially copyable and not guaranteed to be mapped correctly}} + for (GoodIter I(nullptr); I < end; ++I) // expected-warning {{type 'GoodIter' is not trivially copyable and not guaranteed to be mapped correctly}} ++I; #pragma omp target #pragma omp teams distribute simd // expected-warning@+1 {{initialization clause of OpenMP for loop is not in canonical form ('var = init' or 'T var = init')}} - for (GoodIter I(0); I < end; ++I) // expected-warning {{Type 'GoodIter' is not trivially copyable and not guaranteed to be mapped correctly}} + for (GoodIter I(0); I < end; ++I) // expected-warning {{type 'GoodIter' is not trivially copyable and not guaranteed to be mapped correctly}} ++I; #pragma omp target #pragma omp teams distribute simd // expected-warning@+1 {{initialization clause of OpenMP for loop is not in canonical form ('var = init' or 'T var = init')}} - for (GoodIter I(1, 2); I < end; ++I) // expected-warning {{Type 'GoodIter' is not trivially copyable and not guaranteed to be mapped correctly}} + for (GoodIter I(1, 2); I < end; ++I) // expected-warning {{type 'GoodIter' is not trivially copyable and not guaranteed to be mapped correctly}} ++I; #pragma omp target #pragma omp teams distribute simd - for (begin = GoodIter(0); begin < end; ++begin) // expected-warning 2 {{Type 'GoodIter' is not trivially copyable and not guaranteed to be mapped correctly}} + for (begin = GoodIter(0); begin < end; ++begin) // expected-warning 2 {{type 'GoodIter' is not trivially copyable and not guaranteed to be mapped correctly}} ++begin; #pragma omp target #pragma omp teams distribute simd @@ -464,7 +464,7 @@ int test_with_random_access_iterator() { ++begin; #pragma omp target #pragma omp teams distribute simd - for (begin = end; begin < end; ++begin) // expected-warning 2 {{Type 'GoodIter' is not trivially copyable and not guaranteed to be mapped correctly}} + for (begin = end; begin < end; ++begin) // expected-warning 2 {{type 'GoodIter' is not trivially copyable and not guaranteed to be mapped correctly}} ++begin; #pragma omp target #pragma omp teams distribute simd @@ -489,7 +489,7 @@ int test_with_random_access_iterator() { ++I; #pragma omp target #pragma omp teams distribute simd - for (GoodIter I = begin; I >= end; I = I - 1) // expected-warning 2 {{Type 'GoodIter' is not trivially copyable and not guaranteed to be mapped correctly}} + for (GoodIter I = begin; I >= end; I = I - 1) // expected-warning 2 {{type 'GoodIter' is not trivially copyable and not guaranteed to be mapped correctly}} ++I; #pragma omp target #pragma omp teams distribute simd @@ -551,19 +551,19 @@ public: #pragma omp teams distribute simd // expected-note@+2 {{loop step is expected to be positive due to this condition}} // expected-error@+1 {{increment expression must cause 'I' to increase on each iteration of OpenMP for loop}} - for (IT I = begin; I < end; I = I + ST) { // expected-warning 2 {{Type 'GoodIter' is not trivially copyable and not guaranteed to be mapped correctly}} + for (IT I = begin; I < end; I = I + ST) { // expected-warning 2 {{type 'GoodIter' is not trivially copyable and not guaranteed to be mapped correctly}} ++I; } #pragma omp target #pragma omp teams distribute simd // expected-note@+2 {{loop step is expected to be positive due to this condition}} // expected-error@+1 {{increment expression must cause 'I' to increase on each iteration of OpenMP for loop}} - for (IT I = begin; I <= end; I += ST) { // expected-warning 2 {{Type 'GoodIter' is not trivially copyable and not guaranteed to be mapped correctly}} + for (IT I = begin; I <= end; I += ST) { // expected-warning 2 {{type 'GoodIter' is not trivially copyable and not guaranteed to be mapped correctly}} ++I; } #pragma omp target #pragma omp teams distribute simd - for (IT I = begin; I < end; ++I) { // expected-warning 4 {{Type 'GoodIter' is not trivially copyable and not guaranteed to be mapped correctly}} + for (IT I = begin; I < end; ++I) { // expected-warning 4 {{type 'GoodIter' is not trivially copyable and not guaranteed to be mapped correctly}} ++I; } } @@ -599,7 +599,7 @@ int dotest_gt(IT begin, IT end) { #pragma omp target #pragma omp teams distribute simd - for (IT I = begin; I < end; I += TC::step()) { // expected-warning 2 {{Type 'GoodIter' is not trivially copyable and not guaranteed to be mapped correctly}} + for (IT I = begin; I < end; I += TC::step()) { // expected-warning 2 {{type 'GoodIter' is not trivially copyable and not guaranteed to be mapped correctly}} ++I; } } @@ -699,7 +699,7 @@ void test_loop_firstprivate_lastprivate() { S s(4); // expected-error@+2 {{lastprivate variable cannot be firstprivate}} expected-note@+2 {{defined as lastprivate}} #pragma omp target -#pragma omp teams distribute simd lastprivate(s) firstprivate(s) // expected-error {{calling a private constructor of class 'S'}} expected-warning {{Type 'S' is not trivially copyable and not guaranteed to be mapped correctly}} +#pragma omp teams distribute simd lastprivate(s) firstprivate(s) // expected-error {{calling a private constructor of class 'S'}} expected-warning {{type 'S' is not trivially copyable and not guaranteed to be mapped correctly}} for (int i = 0; i < 16; ++i) ; } -- GitLab From 50574638140dc5083d0f272c5279f2ee5d97a833 Mon Sep 17 00:00:00 2001 From: Amir Ayupov Date: Wed, 22 May 2024 10:39:27 -0700 Subject: [PATCH 165/452] [BOLT][NFC] Make BAT methods const (#91823) --- .../bolt/Profile/BoltAddressTranslation.h | 7 +++--- bolt/lib/Profile/BoltAddressTranslation.cpp | 25 +++++++++++-------- 2 files changed, 18 insertions(+), 14 deletions(-) diff --git a/bolt/include/bolt/Profile/BoltAddressTranslation.h b/bolt/include/bolt/Profile/BoltAddressTranslation.h index dcbcd0f60114..7f625674e6bc 100644 --- a/bolt/include/bolt/Profile/BoltAddressTranslation.h +++ b/bolt/include/bolt/Profile/BoltAddressTranslation.h @@ -90,7 +90,7 @@ public: std::error_code parse(raw_ostream &OS, StringRef Buf); /// Dump the parsed address translation tables - void dump(raw_ostream &OS); + void dump(raw_ostream &OS) const; /// If the maps are loaded in memory, perform the lookup to translate LBR /// addresses in function located at \p FuncAddress. @@ -137,7 +137,8 @@ private: /// emitted for the start of the BB. More entries may be emitted to cover /// the location of calls or any instruction that may change control flow. void writeEntriesForBB(MapTy &Map, const BinaryBasicBlock &BB, - uint64_t FuncInputAddress, uint64_t FuncOutputAddress); + uint64_t FuncInputAddress, + uint64_t FuncOutputAddress) const; /// Write the serialized address translation table for a function. template @@ -152,7 +153,7 @@ private: /// Returns the bitmask with set bits corresponding to indices of BRANCHENTRY /// entries in function address translation map. - APInt calculateBranchEntriesBitMask(MapTy &Map, size_t EqualElems); + APInt calculateBranchEntriesBitMask(MapTy &Map, size_t EqualElems) const; /// Calculate the number of equal offsets (output = input - skew) in the /// beginning of the function. diff --git a/bolt/lib/Profile/BoltAddressTranslation.cpp b/bolt/lib/Profile/BoltAddressTranslation.cpp index 8923bee07a31..a9d56875f5a0 100644 --- a/bolt/lib/Profile/BoltAddressTranslation.cpp +++ b/bolt/lib/Profile/BoltAddressTranslation.cpp @@ -20,10 +20,9 @@ namespace bolt { const char *BoltAddressTranslation::SECTION_NAME = ".note.bolt_bat"; -void BoltAddressTranslation::writeEntriesForBB(MapTy &Map, - const BinaryBasicBlock &BB, - uint64_t FuncInputAddress, - uint64_t FuncOutputAddress) { +void BoltAddressTranslation::writeEntriesForBB( + MapTy &Map, const BinaryBasicBlock &BB, uint64_t FuncInputAddress, + uint64_t FuncOutputAddress) const { const uint64_t BBOutputOffset = BB.getOutputAddressRange().first - FuncOutputAddress; const uint32_t BBInputOffset = BB.getInputOffset(); @@ -138,8 +137,8 @@ void BoltAddressTranslation::write(const BinaryContext &BC, raw_ostream &OS) { << " basic block hashes\n"; } -APInt BoltAddressTranslation::calculateBranchEntriesBitMask(MapTy &Map, - size_t EqualElems) { +APInt BoltAddressTranslation::calculateBranchEntriesBitMask( + MapTy &Map, size_t EqualElems) const { APInt BitMask(alignTo(EqualElems, 8), 0); size_t Index = 0; for (std::pair &KeyVal : Map) { @@ -422,7 +421,7 @@ void BoltAddressTranslation::parseMaps(std::vector &HotFuncs, } } -void BoltAddressTranslation::dump(raw_ostream &OS) { +void BoltAddressTranslation::dump(raw_ostream &OS) const { const size_t NumTables = Maps.size(); OS << "BAT tables for " << NumTables << " functions:\n"; for (const auto &MapEntry : Maps) { @@ -447,11 +446,15 @@ void BoltAddressTranslation::dump(raw_ostream &OS) { OS << formatv(" hash: {0:x}", BBHashMap.getBBHash(Val)); OS << "\n"; } - if (IsHotFunction) - OS << "NumBlocks: " << NumBasicBlocksMap[Address] << '\n'; - if (SecondaryEntryPointsMap.count(Address)) { + if (IsHotFunction) { + auto NumBasicBlocksIt = NumBasicBlocksMap.find(Address); + assert(NumBasicBlocksIt != NumBasicBlocksMap.end()); + OS << "NumBlocks: " << NumBasicBlocksIt->second << '\n'; + } + auto SecondaryEntryPointsIt = SecondaryEntryPointsMap.find(Address); + if (SecondaryEntryPointsIt != SecondaryEntryPointsMap.end()) { const std::vector &SecondaryEntryPoints = - SecondaryEntryPointsMap[Address]; + SecondaryEntryPointsIt->second; OS << SecondaryEntryPoints.size() << " secondary entry points:\n"; for (uint32_t EntryPointOffset : SecondaryEntryPoints) OS << formatv("{0:x}\n", EntryPointOffset); -- GitLab From 562c479c6e953f547f95bf6adfb1b17d4c9976be Mon Sep 17 00:00:00 2001 From: Thomas Fransham Date: Wed, 22 May 2024 18:40:13 +0100 Subject: [PATCH 166/452] Set ObjectFile's assignment operator to also be deleted like its copy constructor (#93072) Reapply https://github.com/llvm/llvm-project/pull/92942, this time double checking it compiles. @vgvassilev, @compnerd. --- llvm/include/llvm/Object/ObjectFile.h | 1 + 1 file changed, 1 insertion(+) diff --git a/llvm/include/llvm/Object/ObjectFile.h b/llvm/include/llvm/Object/ObjectFile.h index 8c868c7643ed..f49763e31a9c 100644 --- a/llvm/include/llvm/Object/ObjectFile.h +++ b/llvm/include/llvm/Object/ObjectFile.h @@ -302,6 +302,7 @@ protected: public: ObjectFile() = delete; ObjectFile(const ObjectFile &other) = delete; + ObjectFile &operator=(const ObjectFile &other) = delete; uint64_t getCommonSymbolSize(DataRefImpl Symb) const { Expected SymbolFlagsOrErr = getSymbolFlags(Symb); -- GitLab From 554c47c8e925c5a1d26bd8590695155086a15ab7 Mon Sep 17 00:00:00 2001 From: Alexey Bataev Date: Wed, 22 May 2024 10:17:55 -0700 Subject: [PATCH 167/452] [SLP]Fix undef poison vector values shuffles with poisonous vectors. If trying to find vector value in shuffling of the extractelements and one of the vector values is undef value, need to generate real mask value for such vector and either undef vector, or incoming second vector, if non-poisonous. --- .../Transforms/Vectorize/SLPVectorizer.cpp | 41 +++++++++++++------ .../AMDGPU/crash_extract_subvector_cost.ll | 2 +- .../SLPVectorizer/X86/blending-shuffle.ll | 7 ++-- 3 files changed, 33 insertions(+), 17 deletions(-) diff --git a/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp b/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp index 339b3c2b5f91..08ecbe304429 100644 --- a/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp +++ b/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp @@ -502,6 +502,15 @@ isFixedVectorShuffle(ArrayRef VL, SmallVectorImpl &Mask) { cast(EI0->getVectorOperandType())->getNumElements(); Value *Vec1 = nullptr; Value *Vec2 = nullptr; + bool HasNonUndefVec = any_of(VL, [](Value *V) { + auto *EE = dyn_cast(V); + if (!EE) + return false; + Value *Vec = EE->getVectorOperand(); + if (isa(Vec)) + return false; + return isGuaranteedNotToBePoison(Vec); + }); enum ShuffleMode { Unknown, Select, Permute }; ShuffleMode CommonShuffleMode = Unknown; Mask.assign(VL.size(), PoisonMaskElem); @@ -514,21 +523,27 @@ isFixedVectorShuffle(ArrayRef VL, SmallVectorImpl &Mask) { return std::nullopt; auto *Vec = EI->getVectorOperand(); // We can extractelement from undef or poison vector. - if (isUndefVector(Vec).all()) + if (isUndefVector(Vec).all()) continue; // All vector operands must have the same number of vector elements. - if (cast(Vec->getType())->getNumElements() != Size) - return std::nullopt; - if (isa(EI->getIndexOperand())) - continue; - auto *Idx = dyn_cast(EI->getIndexOperand()); - if (!Idx) - return std::nullopt; - // Undefined behavior if Idx is negative or >= Size. - if (Idx->getValue().uge(Size)) + if (isa(Vec)) { + Mask[I] = I; + } else { + if (cast(Vec->getType())->getNumElements() != Size) + return std::nullopt; + if (isa(EI->getIndexOperand())) + continue; + auto *Idx = dyn_cast(EI->getIndexOperand()); + if (!Idx) + return std::nullopt; + // Undefined behavior if Idx is negative or >= Size. + if (Idx->getValue().uge(Size)) + continue; + unsigned IntIdx = Idx->getValue().getZExtValue(); + Mask[I] = IntIdx; + } + if (isUndefVector(Vec).all() && HasNonUndefVec) continue; - unsigned IntIdx = Idx->getValue().getZExtValue(); - Mask[I] = IntIdx; // For correct shuffling we have to have at most 2 different vector operands // in all extractelement instructions. if (!Vec1 || Vec1 == Vec) { @@ -543,7 +558,7 @@ isFixedVectorShuffle(ArrayRef VL, SmallVectorImpl &Mask) { continue; // If the extract index is not the same as the operation number, it is a // permutation. - if (IntIdx != I) { + if (Mask[I] % Size != I) { CommonShuffleMode = Permute; continue; } diff --git a/llvm/test/Transforms/SLPVectorizer/AMDGPU/crash_extract_subvector_cost.ll b/llvm/test/Transforms/SLPVectorizer/AMDGPU/crash_extract_subvector_cost.ll index e474bab2ad96..e2d25bae95e9 100644 --- a/llvm/test/Transforms/SLPVectorizer/AMDGPU/crash_extract_subvector_cost.ll +++ b/llvm/test/Transforms/SLPVectorizer/AMDGPU/crash_extract_subvector_cost.ll @@ -4,7 +4,7 @@ define <2 x i16> @uadd_sat_v9i16_combine_vi16(<9 x i16> %arg0, <9 x i16> %arg1) { ; CHECK-LABEL: @uadd_sat_v9i16_combine_vi16( ; CHECK-NEXT: bb: -; CHECK-NEXT: [[TMP0:%.*]] = shufflevector <9 x i16> [[ARG0:%.*]], <9 x i16> poison, <2 x i32> +; CHECK-NEXT: [[TMP0:%.*]] = shufflevector <9 x i16> undef, <9 x i16> [[ARG0:%.*]], <2 x i32> ; CHECK-NEXT: [[TMP1:%.*]] = shufflevector <9 x i16> [[ARG1:%.*]], <9 x i16> poison, <2 x i32> ; CHECK-NEXT: [[TMP2:%.*]] = call <2 x i16> @llvm.uadd.sat.v2i16(<2 x i16> [[TMP0]], <2 x i16> [[TMP1]]) ; CHECK-NEXT: ret <2 x i16> [[TMP2]] diff --git a/llvm/test/Transforms/SLPVectorizer/X86/blending-shuffle.ll b/llvm/test/Transforms/SLPVectorizer/X86/blending-shuffle.ll index 4f35b77c50be..8701551f46ab 100644 --- a/llvm/test/Transforms/SLPVectorizer/X86/blending-shuffle.ll +++ b/llvm/test/Transforms/SLPVectorizer/X86/blending-shuffle.ll @@ -39,9 +39,10 @@ define <4 x i8> @h(<4 x i8> %x, <4 x i8> %y) { define <4 x i8> @h_undef(<4 x i8> %x, <4 x i8> %y) { ; CHECK-LABEL: @h_undef( -; CHECK-NEXT: [[TMP1:%.*]] = shufflevector <4 x i8> [[X:%.*]], <4 x i8> [[Y:%.*]], <4 x i32> -; CHECK-NEXT: [[TMP2:%.*]] = mul <4 x i8> [[TMP1]], [[TMP1]] -; CHECK-NEXT: ret <4 x i8> [[TMP2]] +; CHECK-NEXT: [[TMP1:%.*]] = shufflevector <4 x i8> [[X:%.*]], <4 x i8> , <4 x i32> +; CHECK-NEXT: [[TMP2:%.*]] = shufflevector <4 x i8> [[TMP1]], <4 x i8> [[Y:%.*]], <4 x i32> +; CHECK-NEXT: [[TMP3:%.*]] = mul <4 x i8> [[TMP2]], [[TMP2]] +; CHECK-NEXT: ret <4 x i8> [[TMP3]] ; %x0 = extractelement <4 x i8> undef, i32 0 %x3 = extractelement <4 x i8> %x, i32 3 -- GitLab From cc3b6c3ba9c0dd7df0fd7ac23c8609c4675dd62a Mon Sep 17 00:00:00 2001 From: Aaron Ballman Date: Wed, 22 May 2024 13:42:50 -0400 Subject: [PATCH 168/452] Fix more diagnostic wording for style; NFC --- clang/include/clang/Basic/DiagnosticParseKinds.td | 4 ++-- clang/test/Sema/x86-eval-method.c | 4 ++-- clang/test/Sema/x86_64-eval-method.c | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/clang/include/clang/Basic/DiagnosticParseKinds.td b/clang/include/clang/Basic/DiagnosticParseKinds.td index 46656fc66044..d8e89125fae1 100644 --- a/clang/include/clang/Basic/DiagnosticParseKinds.td +++ b/clang/include/clang/Basic/DiagnosticParseKinds.td @@ -1345,8 +1345,8 @@ def note_pragma_attribute_namespace_on_attribute : Note< "omit the namespace to add attributes to the most-recently" " pushed attribute group">; def warn_no_support_for_eval_method_source_on_m32 : Warning< - "Setting the floating point evaluation method to `source` on a target" - " without SSE is not supported.">, InGroup; + "setting the floating point evaluation method to `source` on a target " + "without SSE is not supported">, InGroup; // - #pragma __debug def warn_pragma_debug_dependent_argument : Warning< "%select{value|type}0-dependent expression passed as an argument to debug " diff --git a/clang/test/Sema/x86-eval-method.c b/clang/test/Sema/x86-eval-method.c index f475b0d1b29b..e540a59528b6 100644 --- a/clang/test/Sema/x86-eval-method.c +++ b/clang/test/Sema/x86-eval-method.c @@ -10,9 +10,9 @@ float add1(float a, float b, float c) { return a + b + c; -} // warn-warning{{Setting the floating point evaluation method to `source` on a target without SSE is not supported.}} +} // warn-warning{{setting the floating point evaluation method to `source` on a target without SSE is not supported}} float add2(float a, float b, float c) { #pragma clang fp eval_method(source) return a + b + c; -} // warn-warning{{Setting the floating point evaluation method to `source` on a target without SSE is not supported.}} +} // warn-warning{{setting the floating point evaluation method to `source` on a target without SSE is not supported}} diff --git a/clang/test/Sema/x86_64-eval-method.c b/clang/test/Sema/x86_64-eval-method.c index dbdc1f881b4a..fe4368a42ca1 100644 --- a/clang/test/Sema/x86_64-eval-method.c +++ b/clang/test/Sema/x86_64-eval-method.c @@ -10,4 +10,4 @@ float add2(float a, float b, float c) { #pragma clang fp eval_method(source) return a + b + c; -} // warn-warning{{Setting the floating point evaluation method to `source` on a target without SSE is not supported.}} +} // warn-warning{{setting the floating point evaluation method to `source` on a target without SSE is not supported}} -- GitLab From 96378b3da8c5980471af0046feb0427c77f16c60 Mon Sep 17 00:00:00 2001 From: shaw young <58664393+shawbyoung@users.noreply.github.com> Date: Wed, 22 May 2024 11:04:12 -0700 Subject: [PATCH 169/452] [BOLT] Add NamedRegionTimer to inferStaleProfile (#93078) --- bolt/lib/Profile/StaleProfileMatching.cpp | 6 ++++++ bolt/lib/Rewrite/RewriteInstance.cpp | 6 +----- bolt/lib/Utils/CommandLineOpts.cpp | 4 ++++ 3 files changed, 11 insertions(+), 5 deletions(-) diff --git a/bolt/lib/Profile/StaleProfileMatching.cpp b/bolt/lib/Profile/StaleProfileMatching.cpp index 80c3c072e4ce..365bc5389266 100644 --- a/bolt/lib/Profile/StaleProfileMatching.cpp +++ b/bolt/lib/Profile/StaleProfileMatching.cpp @@ -30,6 +30,7 @@ #include "llvm/ADT/Bitfields.h" #include "llvm/ADT/Hashing.h" #include "llvm/Support/CommandLine.h" +#include "llvm/Support/Timer.h" #include "llvm/Support/xxhash.h" #include "llvm/Transforms/Utils/SampleProfileInference.h" @@ -42,6 +43,7 @@ using namespace llvm; namespace opts { +extern cl::opt TimeRewrite; extern cl::OptionCategory BoltOptCategory; cl::opt @@ -707,6 +709,10 @@ void assignProfile(BinaryFunction &BF, bool YAMLProfileReader::inferStaleProfile( BinaryFunction &BF, const yaml::bolt::BinaryFunctionProfile &YamlBF) { + + NamedRegionTimer T("inferStaleProfile", "stale profile inference", "rewrite", + "Rewrite passes", opts::TimeRewrite); + if (!BF.hasCFG()) return false; diff --git a/bolt/lib/Rewrite/RewriteInstance.cpp b/bolt/lib/Rewrite/RewriteInstance.cpp index 9cc4c8c8c4fa..e3b0917ad18a 100644 --- a/bolt/lib/Rewrite/RewriteInstance.cpp +++ b/bolt/lib/Rewrite/RewriteInstance.cpp @@ -86,6 +86,7 @@ extern cl::list ReorderData; extern cl::opt ReorderFunctions; extern cl::opt TerminalTrap; extern cl::opt TimeBuild; +extern cl::opt TimeRewrite; cl::opt AllowStripped("allow-stripped", cl::desc("allow processing of stripped binaries"), @@ -235,11 +236,6 @@ UseGnuStack("use-gnu-stack", cl::ZeroOrMore, cl::cat(BoltCategory)); -static cl::opt - TimeRewrite("time-rewrite", - cl::desc("print time spent in rewriting passes"), cl::Hidden, - cl::cat(BoltCategory)); - static cl::opt SequentialDisassembly("sequential-disassembly", cl::desc("performs disassembly sequentially"), diff --git a/bolt/lib/Utils/CommandLineOpts.cpp b/bolt/lib/Utils/CommandLineOpts.cpp index ba296c10c00a..41c89bc8aeba 100644 --- a/bolt/lib/Utils/CommandLineOpts.cpp +++ b/bolt/lib/Utils/CommandLineOpts.cpp @@ -179,6 +179,10 @@ cl::opt TimeOpts("time-opts", cl::desc("print time spent in each optimization"), cl::cat(BoltOptCategory)); +cl::opt TimeRewrite("time-rewrite", + cl::desc("print time spent in rewriting passes"), + cl::Hidden, cl::cat(BoltCategory)); + cl::opt UseOldText( "use-old-text", cl::desc("re-use space in old .text if possible (relocation mode)"), -- GitLab From c618ae17341315af5fcc97ffd3ed2b19f6d9e412 Mon Sep 17 00:00:00 2001 From: Joseph Huber Date: Wed, 22 May 2024 13:04:52 -0500 Subject: [PATCH 170/452] [Offload] Rework handling for loading vendor runtimes (#93073) Summary: We previously had multiple options for this, this patch replaces them with `LIBOMPTARGET_DLOPEN_PLUGINS=` to be a list of plugins to dynamically use. It defaults to everything right now. This ignores the `host` plugin because the `libffi` dependency is going to be removed soon hopefully in https://github.com/llvm/llvm-project/pull/91264. --- offload/CMakeLists.txt | 3 +++ offload/cmake/Modules/LibomptargetGetDependencies.cmake | 8 -------- offload/plugins-nextgen/amdgpu/CMakeLists.txt | 3 +-- offload/plugins-nextgen/cuda/CMakeLists.txt | 4 ++-- openmp/docs/SupportAndFAQ.rst | 9 +++++++++ 5 files changed, 15 insertions(+), 12 deletions(-) diff --git a/offload/CMakeLists.txt b/offload/CMakeLists.txt index c3dcebfb7301..8bbdb94c0f65 100644 --- a/offload/CMakeLists.txt +++ b/offload/CMakeLists.txt @@ -146,6 +146,9 @@ endif() message(STATUS "Building the offload library with support for " "the \"${LIBOMPTARGET_PLUGINS_TO_BUILD}\" plugins") +set(LIBOMPTARGET_DLOPEN_PLUGINS "${LIBOMPTARGET_PLUGINS_TO_BUILD}" CACHE STRING + "Semicolon-separated list of plugins to use 'dlopen' for runtime linking") + set(LIBOMPTARGET_ENUM_PLUGIN_TARGETS "") foreach(plugin IN LISTS LIBOMPTARGET_PLUGINS_TO_BUILD) set(LIBOMPTARGET_ENUM_PLUGIN_TARGETS diff --git a/offload/cmake/Modules/LibomptargetGetDependencies.cmake b/offload/cmake/Modules/LibomptargetGetDependencies.cmake index e37b86b2a81f..c296f7ea3863 100644 --- a/offload/cmake/Modules/LibomptargetGetDependencies.cmake +++ b/offload/cmake/Modules/LibomptargetGetDependencies.cmake @@ -3,7 +3,6 @@ # # libffi : required to launch target kernels given function and argument # pointers. -# CUDA : required to control offloading to NVIDIA GPUs. include (FindPackageHandleStandardArgs) @@ -43,13 +42,6 @@ endif() find_package(FFI QUIET) set(LIBOMPTARGET_DEP_LIBFFI_FOUND ${FFI_FOUND}) -################################################################################ -# Looking for CUDA... -################################################################################ - -find_package(CUDAToolkit QUIET) -set(LIBOMPTARGET_DEP_CUDA_FOUND ${CUDAToolkit_FOUND}) - ################################################################################ # Looking for NVIDIA GPUs... ################################################################################ diff --git a/offload/plugins-nextgen/amdgpu/CMakeLists.txt b/offload/plugins-nextgen/amdgpu/CMakeLists.txt index 7630e3788dae..cb9ab8c24084 100644 --- a/offload/plugins-nextgen/amdgpu/CMakeLists.txt +++ b/offload/plugins-nextgen/amdgpu/CMakeLists.txt @@ -13,8 +13,7 @@ target_sources(omptarget.rtl.amdgpu PRIVATE src/rtl.cpp) target_include_directories(omptarget.rtl.amdgpu PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/utils) -option(LIBOMPTARGET_FORCE_DLOPEN_LIBHSA "Build with dlopened libhsa" ON) -if(hsa-runtime64_FOUND AND NOT LIBOMPTARGET_FORCE_DLOPEN_LIBHSA) +if(hsa-runtime64_FOUND AND NOT "amdgpu" IN_LIST LIBOMPTARGET_DLOPEN_PLUGINS) message(STATUS "Building AMDGPU plugin linked against libhsa") target_link_libraries(omptarget.rtl.amdgpu PRIVATE hsa-runtime64::hsa-runtime64) else() diff --git a/offload/plugins-nextgen/cuda/CMakeLists.txt b/offload/plugins-nextgen/cuda/CMakeLists.txt index fa5559c5e7dc..3a3ed6867049 100644 --- a/offload/plugins-nextgen/cuda/CMakeLists.txt +++ b/offload/plugins-nextgen/cuda/CMakeLists.txt @@ -10,8 +10,8 @@ add_target_library(omptarget.rtl.cuda CUDA) target_sources(omptarget.rtl.cuda PRIVATE src/rtl.cpp) -option(LIBOMPTARGET_FORCE_DLOPEN_LIBCUDA "Build with dlopened libcuda" ON) -if(LIBOMPTARGET_DEP_CUDA_FOUND AND NOT LIBOMPTARGET_FORCE_DLOPEN_LIBCUDA) +find_package(CUDAToolkit QUIET) +if(CUDAToolkit_FOUND AND NOT "cuda" IN_LIST LIBOMPTARGET_DLOPEN_PLUGINS) message(STATUS "Building CUDA plugin linked against libcuda") target_link_libraries(omptarget.rtl.cuda PRIVATE CUDA::cuda_driver) else() diff --git a/openmp/docs/SupportAndFAQ.rst b/openmp/docs/SupportAndFAQ.rst index 9e6974dfbb13..a158422befd0 100644 --- a/openmp/docs/SupportAndFAQ.rst +++ b/openmp/docs/SupportAndFAQ.rst @@ -454,6 +454,15 @@ Q: What command line options can I use for OpenMP? We recommend taking a look at the OpenMP :doc:`command line argument reference ` page. +Q: Can I build the offloading runtimes without CUDA or HSA? +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +By default, the offloading runtime will load the associated vendor runtime +during initialization rather than directly linking against them. This allows the +program to be built and run on many machine. If you wish to directly link +against these libraries, use the ``LIBOMPTARGET_DLOPEN_PLUGINS=""`` option to +suppress it for each plugin. The default value is every plugin enabled with +``LIBOMPTARGET_PLUGINS_TO_BUILD``. + Q: Why is my build taking a long time? ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ When installing OpenMP and other LLVM components, the build time on multicore -- GitLab From 29456e9bcc478d458f40a93d309f992f0a314523 Mon Sep 17 00:00:00 2001 From: Zaara Syeda Date: Wed, 22 May 2024 14:07:51 -0400 Subject: [PATCH 171/452] [PowerPC] Fix assembler error with toc-data and data-sections (#91976) We should not emit the label for the toc-data variable when data-sections=false. --- llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp | 6 ++++-- .../PowerPC/toc-data-no-data-sections.ll | 18 ++++++++++++++++++ 2 files changed, 22 insertions(+), 2 deletions(-) create mode 100644 llvm/test/CodeGen/PowerPC/toc-data-no-data-sections.ll diff --git a/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp b/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp index 72e8215fffaf..f4e84ade3b5a 100644 --- a/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp +++ b/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp @@ -2831,8 +2831,10 @@ void PPCAIXAsmPrinter::emitGlobalVariableHelper(const GlobalVariable *GV) { // When -fdata-sections is enabled, every GlobalVariable will // be put into its own csect; therefore, label is not necessary here. - if (!TM.getDataSections() || GV->hasSection()) - OutStreamer->emitLabel(EmittedInitSym); + if (!TM.getDataSections() || GV->hasSection()) { + if (Csect->getMappingClass() != XCOFF::XMC_TD) + OutStreamer->emitLabel(EmittedInitSym); + } // No alias to emit. if (!GOAliasMap[GV].size()) { diff --git a/llvm/test/CodeGen/PowerPC/toc-data-no-data-sections.ll b/llvm/test/CodeGen/PowerPC/toc-data-no-data-sections.ll new file mode 100644 index 000000000000..77851fb83025 --- /dev/null +++ b/llvm/test/CodeGen/PowerPC/toc-data-no-data-sections.ll @@ -0,0 +1,18 @@ +; RUN: llc -mtriple powerpc64-ibm-aix-xcoff -data-sections=false -verify-machineinstrs < %s | FileCheck %s + +@a1 = global i32 0, align 4 #0 + +define void @foo() { +entry: + store i32 1, ptr @a1, align 4 + ret void +} + +attributes #0 = { "toc-data" } + +; CHECK: .toc +; CHECK-NEXT: .csect a1[TD],2 +; CHECK-NEXT: .globl a1[TD] +; CHECK-NEXT: .align 2 +; CHECK-NOT: a1[TD]: +; CHECK-NEXT: .vbyte 4, 0 -- GitLab From 0370beb230a35f00b7d07c50ab95f8777662a0c6 Mon Sep 17 00:00:00 2001 From: Sirraide Date: Wed, 22 May 2024 20:15:44 +0200 Subject: [PATCH 172/452] [Clang] Perform derived-to-base conversion on explicit object parameter in lambda (#89828) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Consider this code: ```c++ template struct Overloaded : Ts... { using Ts::operator()...; }; template Overloaded(Ts...) -> Overloaded; void f() { int x; Overloaded o { [&](this auto& self) { return &x; } }; o(); } ``` To access `x` in the lambda, we need to perform derived-to-base conversion on `self` (since the type of `self` is not the lambda type, but rather `Overloaded<(lambda type)>`). We were previously missing this step, causing us to attempt to load the entire lambda (as the base class, it would end up being the ‘field’ with index `0` here), which would then assert later on in codegen. Moreover, this is only valid in the first place if there is a unique and publicly accessible cast path from the derived class to the lambda’s type, so this also adds a check in Sema to diagnose problematic cases. This fixes #87210 and fixes #89541. --- clang/docs/ReleaseNotes.rst | 3 + clang/include/clang/AST/ASTContext.h | 9 +++ .../clang/Basic/DiagnosticSemaKinds.td | 5 ++ clang/include/clang/Sema/Sema.h | 4 +- clang/lib/CodeGen/CGExpr.cpp | 14 +++- clang/lib/Sema/SemaLambda.cpp | 68 ++++++++++++++---- clang/lib/Sema/SemaOverload.cpp | 15 ++-- clang/test/CXX/drs/cwg28xx.cpp | 71 +++++++++++++++++++ clang/test/CodeGenCXX/cxx2b-deducing-this.cpp | 63 ++++++++++++++++ clang/www/cxx_dr_status.html | 2 +- 10 files changed, 231 insertions(+), 23 deletions(-) diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 2b35e2162ab5..0c4a343b7000 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -766,6 +766,9 @@ Bug Fixes to C++ Support - Clang now correctly diagnoses when the current instantiation is used as an incomplete base class. - Clang no longer treats ``constexpr`` class scope function template specializations of non-static members as implicitly ``const`` in language modes after C++11. +- Fixed a crash when trying to emit captures in a lambda call operator with an explicit object + parameter that is called on a derived type of the lambda. + Fixes (#GH87210), (GH89541). Bug Fixes to AST Handling ^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/clang/include/clang/AST/ASTContext.h b/clang/include/clang/AST/ASTContext.h index 2ce2b810d363..a1d1d1c51cd4 100644 --- a/clang/include/clang/AST/ASTContext.h +++ b/clang/include/clang/AST/ASTContext.h @@ -110,6 +110,9 @@ class VarTemplateDecl; class VTableContextBase; class XRayFunctionFilter; +/// A simple array of base specifiers. +typedef SmallVector CXXCastPath; + namespace Builtin { class Context; @@ -1170,6 +1173,12 @@ public: /// in device compilation. llvm::DenseSet CUDAImplicitHostDeviceFunUsedByDevice; + /// For capturing lambdas with an explicit object parameter whose type is + /// derived from the lambda type, we need to perform derived-to-base + /// conversion so we can access the captures; the cast paths for that + /// are stored here. + llvm::DenseMap LambdaCastPaths; + ASTContext(LangOptions &LOpts, SourceManager &SM, IdentifierTable &idents, SelectorTable &sels, Builtin::Context &builtins, TranslationUnitKind TUKind); diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index 34531411f1c0..761243ed96cb 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -7525,6 +7525,11 @@ def err_explicit_object_parameter_mutable: Error< def err_invalid_explicit_object_type_in_lambda: Error< "invalid explicit object parameter type %0 in lambda with capture; " "the type must be the same as, or derived from, the lambda">; +def err_explicit_object_lambda_ambiguous_base : Error< + "lambda %0 is inaccessible due to ambiguity:%1">; +def err_explicit_object_lambda_inaccessible_base : Error< + "invalid explicit object parameter type %0 in lambda with capture; " + "the type must derive publicly from the lambda">; def err_ref_qualifier_overload : Error< "cannot overload a member function %select{without a ref-qualifier|with " diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index 4e628b21e65e..97784f5ae0dc 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -7071,7 +7071,9 @@ public: StorageClass SC, ArrayRef Params, bool HasExplicitResultType); - void DiagnoseInvalidExplicitObjectParameterInLambda(CXXMethodDecl *Method); + /// Returns true if the explicit object parameter was invalid. + bool DiagnoseInvalidExplicitObjectParameterInLambda(CXXMethodDecl *Method, + SourceLocation CallLoc); /// Perform initialization analysis of the init-capture and perform /// any implicit conversions such as an lvalue-to-rvalue conversion if diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp index 6f9237e2067f..4c4a42134dd4 100644 --- a/clang/lib/CodeGen/CGExpr.cpp +++ b/clang/lib/CodeGen/CGExpr.cpp @@ -4676,7 +4676,8 @@ LValue CodeGenFunction::EmitMemberExpr(const MemberExpr *E) { LValue CodeGenFunction::EmitLValueForLambdaField(const FieldDecl *Field, llvm::Value *ThisValue) { bool HasExplicitObjectParameter = false; - if (const auto *MD = dyn_cast_if_present(CurCodeDecl)) { + const auto *MD = dyn_cast_if_present(CurCodeDecl); + if (MD) { HasExplicitObjectParameter = MD->isExplicitObjectMemberFunction(); assert(MD->getParent()->isLambda()); assert(MD->getParent() == Field->getParent()); @@ -4693,6 +4694,17 @@ LValue CodeGenFunction::EmitLValueForLambdaField(const FieldDecl *Field, else LambdaLV = MakeAddrLValue(AddrOfExplicitObject, D->getType().getNonReferenceType()); + + // Make sure we have an lvalue to the lambda itself and not a derived class. + auto *ThisTy = D->getType().getNonReferenceType()->getAsCXXRecordDecl(); + auto *LambdaTy = cast(Field->getParent()); + if (ThisTy != LambdaTy) { + const CXXCastPath &BasePathArray = getContext().LambdaCastPaths.at(MD); + Address Base = GetAddressOfBaseClass( + LambdaLV.getAddress(*this), ThisTy, BasePathArray.begin(), + BasePathArray.end(), /*NullCheckValue=*/false, SourceLocation()); + LambdaLV = MakeAddrLValue(Base, QualType{LambdaTy->getTypeForDecl(), 0}); + } } else { QualType LambdaTagType = getContext().getTagDeclType(Field->getParent()); LambdaLV = MakeNaturalAlignAddrLValue(ThisValue, LambdaTagType); diff --git a/clang/lib/Sema/SemaLambda.cpp b/clang/lib/Sema/SemaLambda.cpp index 1743afaf1528..276a43ad79b9 100644 --- a/clang/lib/Sema/SemaLambda.cpp +++ b/clang/lib/Sema/SemaLambda.cpp @@ -12,6 +12,7 @@ #include "clang/Sema/SemaLambda.h" #include "TypeLocBuilder.h" #include "clang/AST/ASTLambda.h" +#include "clang/AST/CXXInheritance.h" #include "clang/AST/ExprCXX.h" #include "clang/Basic/TargetInfo.h" #include "clang/Sema/DeclSpec.h" @@ -386,30 +387,69 @@ buildTypeForLambdaCallOperator(Sema &S, clang::CXXRecordDecl *Class, // parameter, if any, of the lambda's function call operator (possibly // instantiated from a function call operator template) shall be either: // - the closure type, -// - class type derived from the closure type, or +// - class type publicly and unambiguously derived from the closure type, or // - a reference to a possibly cv-qualified such type. -void Sema::DiagnoseInvalidExplicitObjectParameterInLambda( - CXXMethodDecl *Method) { +bool Sema::DiagnoseInvalidExplicitObjectParameterInLambda( + CXXMethodDecl *Method, SourceLocation CallLoc) { if (!isLambdaCallWithExplicitObjectParameter(Method)) - return; + return false; CXXRecordDecl *RD = Method->getParent(); if (Method->getType()->isDependentType()) - return; + return false; if (RD->isCapturelessLambda()) - return; - QualType ExplicitObjectParameterType = Method->getParamDecl(0) - ->getType() + return false; + + ParmVarDecl *Param = Method->getParamDecl(0); + QualType ExplicitObjectParameterType = Param->getType() .getNonReferenceType() .getUnqualifiedType() .getDesugaredType(getASTContext()); QualType LambdaType = getASTContext().getRecordType(RD); if (LambdaType == ExplicitObjectParameterType) - return; - if (IsDerivedFrom(RD->getLocation(), ExplicitObjectParameterType, LambdaType)) - return; - Diag(Method->getParamDecl(0)->getLocation(), - diag::err_invalid_explicit_object_type_in_lambda) - << ExplicitObjectParameterType; + return false; + + // Don't check the same instantiation twice. + // + // If this call operator is ill-formed, there is no point in issuing + // a diagnostic every time it is called because the problem is in the + // definition of the derived type, not at the call site. + // + // FIXME: Move this check to where we instantiate the method? This should + // be possible, but the naive approach of just marking the method as invalid + // leads to us emitting more diagnostics than we should have to for this case + // (1 error here *and* 1 error about there being no matching overload at the + // call site). It might be possible to avoid that by also checking if there + // is an empty cast path for the method stored in the context (signalling that + // we've already diagnosed it) and then just not building the call, but that + // doesn't really seem any simpler than diagnosing it at the call site... + if (auto It = Context.LambdaCastPaths.find(Method); + It != Context.LambdaCastPaths.end()) + return It->second.empty(); + + CXXCastPath &Path = Context.LambdaCastPaths[Method]; + CXXBasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/true, + /*DetectVirtual=*/false); + if (!IsDerivedFrom(RD->getLocation(), ExplicitObjectParameterType, LambdaType, + Paths)) { + Diag(Param->getLocation(), diag::err_invalid_explicit_object_type_in_lambda) + << ExplicitObjectParameterType; + return true; + } + + if (Paths.isAmbiguous(LambdaType->getCanonicalTypeUnqualified())) { + std::string PathsDisplay = getAmbiguousPathsDisplayString(Paths); + Diag(CallLoc, diag::err_explicit_object_lambda_ambiguous_base) + << LambdaType << PathsDisplay; + return true; + } + + if (CheckBaseClassAccess(CallLoc, LambdaType, ExplicitObjectParameterType, + Paths.front(), + diag::err_explicit_object_lambda_inaccessible_base)) + return true; + + BuildBasePathArray(Paths, Path); + return false; } void Sema::handleLambdaNumbering( diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp index 2eb25237a0de..0c89fca8d38e 100644 --- a/clang/lib/Sema/SemaOverload.cpp +++ b/clang/lib/Sema/SemaOverload.cpp @@ -6472,17 +6472,20 @@ ExprResult Sema::InitializeExplicitObjectArgument(Sema &S, Expr *Obj, Obj->getExprLoc(), Obj); } -static void PrepareExplicitObjectArgument(Sema &S, CXXMethodDecl *Method, +static bool PrepareExplicitObjectArgument(Sema &S, CXXMethodDecl *Method, Expr *Object, MultiExprArg &Args, SmallVectorImpl &NewArgs) { assert(Method->isExplicitObjectMemberFunction() && "Method is not an explicit member function"); assert(NewArgs.empty() && "NewArgs should be empty"); + NewArgs.reserve(Args.size() + 1); Expr *This = GetExplicitObjectExpr(S, Object, Method); NewArgs.push_back(This); NewArgs.append(Args.begin(), Args.end()); Args = NewArgs; + return S.DiagnoseInvalidExplicitObjectParameterInLambda( + Method, Object->getBeginLoc()); } /// Determine whether the provided type is an integral type, or an enumeration @@ -15612,8 +15615,10 @@ ExprResult Sema::BuildCallToMemberFunction(Scope *S, Expr *MemExprE, CallExpr *TheCall = nullptr; llvm::SmallVector NewArgs; if (Method->isExplicitObjectMemberFunction()) { - PrepareExplicitObjectArgument(*this, Method, MemExpr->getBase(), Args, - NewArgs); + if (PrepareExplicitObjectArgument(*this, Method, MemExpr->getBase(), Args, + NewArgs)) + return ExprError(); + // Build the actual expression node. ExprResult FnExpr = CreateFunctionRefExpr(*this, Method, FoundDecl, MemExpr, @@ -15927,9 +15932,7 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Obj, // Initialize the object parameter. llvm::SmallVector NewArgs; if (Method->isExplicitObjectMemberFunction()) { - // FIXME: we should do that during the definition of the lambda when we can. - DiagnoseInvalidExplicitObjectParameterInLambda(Method); - PrepareExplicitObjectArgument(*this, Method, Obj, Args, NewArgs); + IsError |= PrepareExplicitObjectArgument(*this, Method, Obj, Args, NewArgs); } else { ExprResult ObjRes = PerformImplicitObjectArgumentInitialization( Object.get(), /*Qualifier=*/nullptr, Best->FoundDecl, Method); diff --git a/clang/test/CXX/drs/cwg28xx.cpp b/clang/test/CXX/drs/cwg28xx.cpp index 696cd1b9c84e..8469a065ccaa 100644 --- a/clang/test/CXX/drs/cwg28xx.cpp +++ b/clang/test/CXX/drs/cwg28xx.cpp @@ -109,3 +109,74 @@ struct A { #endif } // namespace cwg2858 + +namespace cwg2881 { // cwg2881: 19 tentatively ready 2024-04-19 + +#if __cplusplus >= 202302L + +template struct A : T {}; +template struct B : T {}; +template struct C : virtual T { C(T t) : T(t) {} }; +template struct D : virtual T { D(T t) : T(t) {} }; + +template +struct O1 : A, B { + using A::operator(); + using B::operator(); +}; + +template struct O2 : protected Ts { // expected-note {{declared protected here}} + using Ts::operator(); + O2(Ts ts) : Ts(ts) {} +}; + +template struct O3 : private Ts { // expected-note {{declared private here}} + using Ts::operator(); + O3(Ts ts) : Ts(ts) {} +}; + +// Not ambiguous because of virtual inheritance. +template +struct O4 : C, D { + using C::operator(); + using D::operator(); + O4(Ts t) : Ts(t), C(t), D(t) {} +}; + +// This still has a public path to the lambda, and it's also not +// ambiguous because of virtual inheritance. +template +struct O5 : private C, D { + using C::operator(); + using D::operator(); + O5(Ts t) : Ts(t), C(t), D(t) {} +}; + +// This is only invalid if we call T's call operator. +template +struct O6 : private T, U { // expected-note {{declared private here}} + using T::operator(); + using U::operator(); + O6(T t, U u) : T(t), U(u) {} +}; + +void f() { + int x; + auto L1 = [=](this auto&& self) { (void) &x; }; + auto L2 = [&](this auto&& self) { (void) &x; }; + O1{L1, L1}(); // expected-error {{inaccessible due to ambiguity}} + O1{L2, L2}(); // expected-error {{inaccessible due to ambiguity}} + O2{L1}(); // expected-error {{must derive publicly from the lambda}} + O3{L1}(); // expected-error {{must derive publicly from the lambda}} + O4{L1}(); + O5{L1}(); + O6 o{L1, L2}; + o.decltype(L1)::operator()(); // expected-error {{must derive publicly from the lambda}} + o.decltype(L1)::operator()(); // No error here because we've already diagnosed this method. + o.decltype(L2)::operator()(); +} + +#endif + +} // namespace cwg2881 + diff --git a/clang/test/CodeGenCXX/cxx2b-deducing-this.cpp b/clang/test/CodeGenCXX/cxx2b-deducing-this.cpp index b755e80db35a..649fe2afbf4e 100644 --- a/clang/test/CodeGenCXX/cxx2b-deducing-this.cpp +++ b/clang/test/CodeGenCXX/cxx2b-deducing-this.cpp @@ -182,3 +182,66 @@ auto dothing(int num) fun(); } } + +namespace GH87210 { +template +struct Overloaded : Ts... { + using Ts::operator()...; +}; + +template +Overloaded(Ts...) -> Overloaded; + +// CHECK-LABEL: define dso_local void @_ZN7GH872101fEv() +// CHECK-NEXT: entry: +// CHECK-NEXT: [[X:%.*]] = alloca i32 +// CHECK-NEXT: [[Over:%.*]] = alloca %"{{.*}}Overloaded" +// CHECK: call noundef ptr @"_ZZN7GH872101fEvENH3$_0clINS_10OverloadedIJS0_EEEEEDaRT_"(ptr {{.*}} [[Over]]) +void f() { + int x; + Overloaded o { + // CHECK: define internal noundef ptr @"_ZZN7GH872101fEvENH3$_0clINS_10OverloadedIJS0_EEEEEDaRT_"(ptr {{.*}} [[Self:%.*]]) + // CHECK-NEXT: entry: + // CHECK-NEXT: [[SelfAddr:%.*]] = alloca ptr + // CHECK-NEXT: store ptr [[Self]], ptr [[SelfAddr]] + // CHECK-NEXT: [[SelfPtr:%.*]] = load ptr, ptr [[SelfAddr]] + // CHECK-NEXT: [[XRef:%.*]] = getelementptr inbounds %{{.*}}, ptr [[SelfPtr]], i32 0, i32 0 + // CHECK-NEXT: [[X:%.*]] = load ptr, ptr [[XRef]] + // CHECK-NEXT: ret ptr [[X]] + [&](this auto& self) { + return &x; + } + }; + o(); +} + +void g() { + int x; + Overloaded o { + [=](this auto& self) { + return x; + } + }; + o(); +} +} + +namespace GH89541 { +// Same as above; just check that this doesn't crash. +int one = 1; +auto factory(int& x = one) { + return [&](this auto self) { + x; + }; +}; + +using Base = decltype(factory()); +struct Derived : Base { + Derived() : Base(factory()) {} +}; + +void f() { + Derived d; + d(); +} +} diff --git a/clang/www/cxx_dr_status.html b/clang/www/cxx_dr_status.html index 9d458330f537..8d9b83aa29bf 100755 --- a/clang/www/cxx_dr_status.html +++ b/clang/www/cxx_dr_status.html @@ -17095,7 +17095,7 @@ objects 2881 tentatively ready Type restrictions for the explicit object parameter of a lambda - Not resolved + Not Resolved* 2882 -- GitLab From 9329b20d5d906c59f7d21ac013b908930d496374 Mon Sep 17 00:00:00 2001 From: Kunwar Grover Date: Wed, 22 May 2024 19:21:20 +0100 Subject: [PATCH 173/452] [mlir][TilingInterface] Allow multiple results in PartialReductionOpInterface (#92624) This patch adds support for reducing operations with multiple results using PartialReductionOpInterface. Also adds an implementation of PartialReductionOpInterface for multiple results for linalg.generic. --- .../Linalg/TransformOps/LinalgTransformOps.td | 4 +- .../Dialect/Linalg/Transforms/Transforms.h | 4 +- .../SCF/Transforms/TileUsingInterface.h | 4 +- .../mlir/Interfaces/TilingInterface.td | 4 +- .../TransformOps/LinalgTransformOps.cpp | 6 +- .../Transforms/MeshShardingInterfaceImpl.cpp | 11 +- mlir/lib/Dialect/Linalg/Transforms/Tiling.cpp | 17 +- .../Linalg/Transforms/TilingInterfaceImpl.cpp | 243 ++++++++++-------- .../SCF/Transforms/TileUsingInterface.cpp | 42 ++- .../Linalg/transform-tile-reduction.mlir | 50 +++- 10 files changed, 236 insertions(+), 149 deletions(-) diff --git a/mlir/include/mlir/Dialect/Linalg/TransformOps/LinalgTransformOps.td b/mlir/include/mlir/Dialect/Linalg/TransformOps/LinalgTransformOps.td index 5585ba27fdad..93e2c2db729d 100644 --- a/mlir/include/mlir/Dialect/Linalg/TransformOps/LinalgTransformOps.td +++ b/mlir/include/mlir/Dialect/Linalg/TransformOps/LinalgTransformOps.td @@ -1681,7 +1681,7 @@ def TileReductionUsingForOp : Op:$tile_sizes); - let results = (outs TransformHandleTypeInterface:$fill_op, + let results = (outs Variadic:$fill_op, TransformHandleTypeInterface:$split_linalg_op, TransformHandleTypeInterface:$combining_linalg_op, TransformHandleTypeInterface:$for_op); @@ -1787,7 +1787,7 @@ def TileReductionUsingForallOp : DefaultValuedAttr:$num_threads, DefaultValuedAttr:$tile_sizes, OptionalAttr:$mapping); - let results = (outs TransformHandleTypeInterface:$fill_op, + let results = (outs Variadic:$fill_op, TransformHandleTypeInterface:$split_linalg_op, TransformHandleTypeInterface:$combining_linalg_op, TransformHandleTypeInterface:$forall_op); diff --git a/mlir/include/mlir/Dialect/Linalg/Transforms/Transforms.h b/mlir/include/mlir/Dialect/Linalg/Transforms/Transforms.h index f77c19ed0fcc..308ce92e3552 100644 --- a/mlir/include/mlir/Dialect/Linalg/Transforms/Transforms.h +++ b/mlir/include/mlir/Dialect/Linalg/Transforms/Transforms.h @@ -876,8 +876,8 @@ struct ForallReductionTilingResult { Operation *parallelTiledOp; /// The final reduction operation merging all the partial reductions. Operation *mergeOp; - /// The op initializing the tensor used for partial reductions. - Operation *initialOp; + /// Initial values used for partial reductions. + SmallVector initialValues; /// The `scf.forall` operation that iterate over the tiles. scf::ForallOp loops; }; diff --git a/mlir/include/mlir/Dialect/SCF/Transforms/TileUsingInterface.h b/mlir/include/mlir/Dialect/SCF/Transforms/TileUsingInterface.h index 965ef9e203be..6d567171e185 100644 --- a/mlir/include/mlir/Dialect/SCF/Transforms/TileUsingInterface.h +++ b/mlir/include/mlir/Dialect/SCF/Transforms/TileUsingInterface.h @@ -250,8 +250,8 @@ struct SCFReductionTilingResult { Operation *parallelTiledOp; /// The final reduction operation merging all the partial reductions. Operation *mergeOp; - /// Initial op - Operation *initialOp; + /// Initial values used for reduction. + SmallVector initialValues; /// The loop operations that iterate over the tiles. SmallVector loops; }; diff --git a/mlir/include/mlir/Interfaces/TilingInterface.td b/mlir/include/mlir/Interfaces/TilingInterface.td index 66382f29c242..14d775d986d2 100644 --- a/mlir/include/mlir/Interfaces/TilingInterface.td +++ b/mlir/include/mlir/Interfaces/TilingInterface.td @@ -170,11 +170,11 @@ def PartialReductionOpInterface : OpInterface<"PartialReductionOpInterface"> { operation reduction. The tensor shape is equal to operation result shape with new dimension for each non zero tile size. }], - /*retType=*/"FailureOr", + /*retType=*/"FailureOr>", /*methodName=*/"generateInitialTensorForPartialReduction", /*args=*/(ins "OpBuilder &":$b, - "Location ":$loc, + "Location":$loc, "ArrayRef":$sizes, "ArrayRef":$reductionDim), /*methodBody=*/"", diff --git a/mlir/lib/Dialect/Linalg/TransformOps/LinalgTransformOps.cpp b/mlir/lib/Dialect/Linalg/TransformOps/LinalgTransformOps.cpp index 13582a140a96..9b3121774ab3 100644 --- a/mlir/lib/Dialect/Linalg/TransformOps/LinalgTransformOps.cpp +++ b/mlir/lib/Dialect/Linalg/TransformOps/LinalgTransformOps.cpp @@ -2523,7 +2523,8 @@ DiagnosedSilenceableFailure transform::TileReductionUsingForOp::applyToOne( if (failed(result)) return emitDefaultSilenceableFailure(target); - results.push_back(result->initialOp); + for (Value initValue : result->initialValues) + results.push_back(initValue.getDefiningOp()); results.push_back(result->parallelTiledOp); results.push_back(result->mergeOp); results.push_back(result->loops.front()); @@ -2574,7 +2575,8 @@ DiagnosedSilenceableFailure transform::TileReductionUsingForallOp::applyToOne( diag.attachNote(target.getLoc()) << "target operation"; return diag; } - results.push_back(result->initialOp); + for (Value initValue : result->initialValues) + results.push_back(initValue.getDefiningOp()); results.push_back(result->parallelTiledOp); results.push_back(result->mergeOp); results.push_back(result->loops); diff --git a/mlir/lib/Dialect/Linalg/Transforms/MeshShardingInterfaceImpl.cpp b/mlir/lib/Dialect/Linalg/Transforms/MeshShardingInterfaceImpl.cpp index 146e88076566..b145e4c8fc94 100644 --- a/mlir/lib/Dialect/Linalg/Transforms/MeshShardingInterfaceImpl.cpp +++ b/mlir/lib/Dialect/Linalg/Transforms/MeshShardingInterfaceImpl.cpp @@ -155,12 +155,12 @@ static Value createDestinationPassingStyleInitOperand( tensor::getMixedSizes(builder, builder.getLoc(), spmdizedOperand); PartialReductionOpInterface partialReductionIface = llvm::cast(op.getOperation()); - FailureOr reductionNeutralTensorOp = + assert(op->getNumResults() == 1 && "Multiple results not supported."); + FailureOr> reductionNeutralTensor = partialReductionIface.generateInitialTensorForPartialReduction( builder, builder.getLoc(), shape, {}); - assert(succeeded(reductionNeutralTensorOp)); - builder.create( - reductionNeutralTensorOp.value()->getResult(0)); + assert(succeeded(reductionNeutralTensor)); + builder.create(reductionNeutralTensor.value()); } return ifOp.getResult(0); } @@ -173,8 +173,7 @@ static SmallVector createDestinationPassingStyleInitOperands( ImplicitLocOpBuilder &builder) { // TODO: add support for multiple destination passing style initial value // operands. - // PartialReductionOpInterface::generateInitialTensorForPartialReduction - // needs to also support multiple DPS initial operands. + assert(op.getNumDpsInits() == 1 && "Multiple initial values not supported."); SmallVector newOperands = llvm::to_vector(spmdizedOperands); auto operandIdx = op.getDpsInitOperand(0)->getOperandNumber(); Value spmdizedInitOperand = diff --git a/mlir/lib/Dialect/Linalg/Transforms/Tiling.cpp b/mlir/lib/Dialect/Linalg/Transforms/Tiling.cpp index df4089d61bfd..fd314ef9f813 100644 --- a/mlir/lib/Dialect/Linalg/Transforms/Tiling.cpp +++ b/mlir/lib/Dialect/Linalg/Transforms/Tiling.cpp @@ -692,12 +692,13 @@ FailureOr linalg::tileReductionUsingForall( op, "reduction dimension must be mapped to threads"); // 1. Create the inital tensor value. - FailureOr identityTensor = + FailureOr> maybeInitTensors = op.generateInitialTensorForPartialReduction(b, loc, numThreads, reductionDim); - if (failed(identityTensor)) - return b.notifyMatchFailure(op, - "cannot create a tensor of identity value."); + if (failed(maybeInitTensors)) + return b.notifyMatchFailure( + op, "Failed to create inital tensors for partial reduction"); + SmallVector &initTensors = maybeInitTensors.value(); // Gather destination tensors. SmallVector dest; @@ -715,8 +716,8 @@ FailureOr linalg::tileReductionUsingForall( // 2. Create the ForallOp with an empty region. scf::ForallOp forallOp = b.create( - loc, getAsOpFoldResult(materializedNonZeroNumThreads), - (*identityTensor)->getResults(), mapping); + loc, getAsOpFoldResult(materializedNonZeroNumThreads), initTensors, + mapping); // 3. Calculate the tile offsets and sizes for the subsequent loop that will // be nested under `forallOp`. @@ -726,7 +727,7 @@ FailureOr linalg::tileReductionUsingForall( /*nominalTileSizes=*/std::nullopt, tiledOffsets, tiledSizes); - // 4. Clone the tileable op and update its destination operands to use the + // 4b. Clone the tileable op and update its destination operands to use the // output bbArgs of the ForallOp. SmallVector tilingResults; ArrayRef destBbArgs = forallOp.getRegionIterArgs(); @@ -838,7 +839,7 @@ FailureOr linalg::tileReductionUsingForall( // 8. Return. ForallReductionTilingResult results; - results.initialOp = *identityTensor; + results.initialValues = initTensors; results.loops = forallOp; results.parallelTiledOp = tiledOp; results.mergeOp = mergeOp; diff --git a/mlir/lib/Dialect/Linalg/Transforms/TilingInterfaceImpl.cpp b/mlir/lib/Dialect/Linalg/Transforms/TilingInterfaceImpl.cpp index bd870d4f982e..f512be46cc13 100644 --- a/mlir/lib/Dialect/Linalg/Transforms/TilingInterfaceImpl.cpp +++ b/mlir/lib/Dialect/Linalg/Transforms/TilingInterfaceImpl.cpp @@ -250,7 +250,7 @@ template struct LinalgOpPartialReductionInterface : public PartialReductionOpInterface::ExternalModel< LinalgOpPartialReductionInterface, LinalgOpTy> { - FailureOr generateInitialTensorForPartialReduction( + FailureOr> generateInitialTensorForPartialReduction( Operation *op, OpBuilder &b, Location loc, ArrayRef sizes, ArrayRef reductionDims) const { auto linalgOp = cast(op); @@ -258,50 +258,58 @@ struct LinalgOpPartialReductionInterface if (linalgOp.hasPureBufferSemantics()) return op->emitOpError("expected operation to have tensor semantics"); - // Insert the new parallel dimension based on the index of the reduction - // loops. This could be controlled by user for more flexibility. - SmallVector combinerOps; - if (!matchReduction(linalgOp.getRegionOutputArgs(), 0, combinerOps) || - combinerOps.size() != 1) - return op->emitOpError("Failed to anaysis the reduction operation."); - - Operation *reductionOp = combinerOps[0]; - std::optional identity = arith::getNeutralElement(reductionOp); - if (!identity.has_value()) - return op->emitOpError( - "Failed to get an identity value for the reduction operation."); - - ArrayRef oldShape = - linalgOp.getShape(linalgOp.getDpsInitOperand(0)); - - // Calculate the new shape, we insert the new dimensions based on the index - // of the reduction dimensions. - SmallVector newOutputShape; - SmallVector dynamicDims; - int64_t currReductionDims = 0; - DenseSet reductionDimsSet(reductionDims.begin(), reductionDims.end()); - for (int64_t idx : - llvm::seq(0, oldShape.size() + reductionDims.size())) { - if (reductionDimsSet.contains(idx)) { - dispatchIndexOpFoldResults(sizes[idx], dynamicDims, newOutputShape); - currReductionDims++; - continue; + SmallVector inits; + for (int initIdx = 0, e = linalgOp.getNumDpsInits(); initIdx < e; + ++initIdx) { + // Insert the new parallel dimension based on the index of the reduction + // loops. This could be controlled by user for more flexibility. + SmallVector combinerOps; + if (!matchReduction(linalgOp.getRegionOutputArgs(), initIdx, + combinerOps) || + combinerOps.size() != 1) + return op->emitOpError("Failed to anaysis the reduction operation."); + + Operation *reductionOp = combinerOps[0]; + std::optional identity = arith::getNeutralElement(reductionOp); + if (!identity.has_value()) + return op->emitOpError( + "Failed to get an identity value for the reduction operation."); + + ArrayRef oldShape = + linalgOp.getShape(linalgOp.getDpsInitOperand(initIdx)); + + // Calculate the new shape, we insert the new dimensions based on the + // index of the reduction dimensions. + SmallVector newOutputShape; + SmallVector dynamicDims; + int64_t currReductionDims = 0; + DenseSet reductionDimsSet(reductionDims.begin(), + reductionDims.end()); + for (int64_t idx : + llvm::seq(0, oldShape.size() + reductionDims.size())) { + if (reductionDimsSet.contains(idx)) { + dispatchIndexOpFoldResults(sizes[idx], dynamicDims, newOutputShape); + currReductionDims++; + continue; + } + int64_t oldIdx = idx - currReductionDims; + int64_t dim = oldShape[oldIdx]; + newOutputShape.push_back(dim); + if (ShapedType::isDynamic(dim)) + dynamicDims.push_back(b.create( + loc, linalgOp.getDpsInitOperand(initIdx)->get(), oldIdx)); } - int64_t oldIdx = idx - currReductionDims; - int64_t dim = oldShape[oldIdx]; - newOutputShape.push_back(dim); - if (ShapedType::isDynamic(dim)) - dynamicDims.push_back(b.create( - loc, linalgOp.getDpsInitOperand(0)->get(), oldIdx)); + Value emptyTensor = b.create( + loc, newOutputShape, + linalgOp.getRegionOutputArgs()[initIdx].getType(), dynamicDims); + Value constantOp = b.create(loc, *identity); + auto identityTensor = + b.create(loc, constantOp, emptyTensor); + inits.push_back(identityTensor.getResult(0)); } - Value emptyTensor = b.create( - loc, newOutputShape, linalgOp.getRegionOutputArgs()[0].getType(), - dynamicDims); - Value constantOp = b.create(loc, *identity); - auto identityTensor = - b.create(loc, constantOp, emptyTensor); - return identityTensor.getOperation(); + + return inits; } Operation *tileToPartialReduction(Operation *op, OpBuilder &b, Location loc, @@ -312,44 +320,64 @@ struct LinalgOpPartialReductionInterface OpBuilder::InsertionGuard guard(b); auto linalgOp = cast(op); - AffineMap oldOutputMap = - linalgOp.getMatchingIndexingMap(linalgOp.getDpsInitOperand(0)); - SmallVector outputExpr(oldOutputMap.getNumResults() + - reductionDims.size()); - - for (int idx : reductionDims) - outputExpr[idx] = b.getAffineDimExpr(idx); - int currExpr = 0; - for (int idx : llvm::seq(0, outputExpr.size())) { - if (outputExpr[idx]) - continue; - outputExpr[idx] = oldOutputMap.getResult(currExpr++); + // Step 1. Extend init maps to have reduction dimension dims, since we + // are converting them to parallel dimensions. + SmallVector newInitMaps; + newInitMaps.reserve(linalgOp.getNumDpsInits()); + for (int idx : llvm::seq(0, linalgOp.getNumDpsInits())) { + // TODO: linalg::Generic doesn't have getDpsInitOperands. Can replace + // this with a for range loop when we have it. + AffineMap newMap = + linalgOp.getMatchingIndexingMap(linalgOp.getDpsInitOperand(idx)); + for (int redPos : reductionDims) { + newMap = newMap.insertResult(b.getAffineDimExpr(redPos), + newMap.getNumResults()); + } + newInitMaps.push_back(newMap); } - // Step 1: Extract a slice of the input operands. - SmallVector valuesToTile = linalgOp.getDpsInputs(); - SmallVector tiledOperands = makeTiledShapes( - b, loc, linalgOp, valuesToTile, offsets, sizes, {}, true); + // Step 2a: Extract a slice of the input operands. + SmallVector tiledInputs = makeTiledShapes( + b, loc, linalgOp, linalgOp.getDpsInputs(), offsets, sizes, {}, true); + + // Step 2b: Extract a slice of the init operands. + SmallVector tiledInits; + for (auto [valueMap, valueToTile] : llvm::zip_equal(newInitMaps, init)) { + int64_t initRank = valueMap.getNumResults(); + SmallVector initOffset(initRank, b.getIndexAttr(0)); + SmallVector initStride(initRank, b.getIndexAttr(1)); + SmallVector initSizes; + for (AffineExpr dimExpr : valueMap.getResults()) { + auto dim = cast(dimExpr); + initSizes.push_back(sizes[dim.getPosition()]); + } + // TODO: Use SubsetExtractOpInterface here once available. + auto extractSlice = b.create( + loc, valueToTile, initOffset, initSizes, initStride); + tiledInits.push_back(extractSlice); + } - // Step 2: Extract the accumulator operands - SmallVector strides(offsets.size(), b.getIndexAttr(1)); - SmallVector outOffsets(offsets.size(), b.getIndexAttr(0)); - // TODO: use SubsetExtractOpInterface once it is available. - Value out = b.create(loc, init[0], outOffsets, - sizes, strides); + // Update the indexing maps. + SmallVector newMaps = linalgOp.getIndexingMapsArray(); + // Change the init maps. + for (int idx : llvm::seq(0, linalgOp.getNumDpsInits())) { + // TODO: linalg::Generic doesn't have getDpsInitOperands. Can replace + // this with a for range loop when we have it. + OpOperand *initOperand = linalgOp.getDpsInitOperand(idx); + int64_t mapIdx = linalgOp.getIndexingMapIndex(initOperand); + newMaps[mapIdx] = newInitMaps[idx]; + } - // Step3. Create a generic op where the reduction dimensions are replaced - // by a parallel dimension of the size of reduction. + // Step 3. Change the reduction dim iterator types. SmallVector newIteratorTypes = linalgOp.getIteratorTypesArray(); for (int dim : reductionDims) newIteratorTypes[dim] = utils::IteratorType::parallel; - SmallVector newMaps = linalgOp.getIndexingMapsArray(); - newMaps.back() = AffineMap::get(newMaps.back().getNumDims(), 0, outputExpr, - linalgOp.getContext()); + + // Step 4. Create the new generic op. auto genericOp = - b.create(loc, TypeRange({out.getType()}), tiledOperands, - ValueRange({out}), newMaps, newIteratorTypes); + b.create(loc, ValueRange(tiledInits).getTypes(), tiledInputs, + tiledInits, newMaps, newIteratorTypes); IRMapping mapping; op->getRegion(0).cloneInto(&genericOp.getRegion(), genericOp.getRegion().begin(), mapping); @@ -361,40 +389,53 @@ struct LinalgOpPartialReductionInterface ArrayRef reductionDims) const { auto linalgOp = cast(op); - DenseSet reductionDimsSet(reductionDims.begin(), reductionDims.end()); - - // Then create a new reduction that only reduce the newly added dimensions - // from the previous op. - int64_t intermRank = cast(partialReduce[0].getType()).getRank(); - AffineMap inputMap = b.getMultiDimIdentityMap(intermRank); - SmallVector reductionIteratorTypes; - SmallVector exprs; - - for (int64_t i : llvm::seq(0, intermRank)) { - if (reductionDimsSet.contains(i)) { - reductionIteratorTypes.push_back(utils::IteratorType::reduction); - } else { - exprs.push_back(b.getAffineDimExpr(i)); - reductionIteratorTypes.push_back(utils::IteratorType::parallel); + // Step 1. Recover the dims that actually need to be merged from the + // original operation. We can classify the original iterators as follows: + // + // parallel --> parallel + // reduction + not in reductionDims --> parallel (already reduced) + // reduction + in reductionDims --> reduction (will reduce now) + SmallVector iterators(linalgOp.getNumLoops(), + utils::IteratorType::parallel); + for (int redIdx : reductionDims) + iterators[redIdx] = utils::IteratorType::reduction; + + // Step 2. For each partial result, create a map to index it. This map + // is simply the indexing map for the original result with reductionDims + // appended (as produced in tileToPartialReduction). + int64_t numInits = linalgOp.getNumDpsInits(); + SmallVector indexingMaps(numInits * 2); + for (int idx : llvm::seq(0, numInits)) { + AffineMap &inputMap = indexingMaps[idx]; + AffineMap &outputMap = indexingMaps[numInits + idx]; + + outputMap = + linalgOp.getMatchingIndexingMap(linalgOp.getDpsInitOperand(idx)); + inputMap = outputMap; + for (int redPos : reductionDims) { + inputMap = inputMap.insertResult(b.getAffineDimExpr(redPos), + inputMap.getNumResults()); } } - AffineMap outputMap = - AffineMap::get(intermRank, 0, exprs, op->getContext()); - SmallVector reductionMaps = {inputMap, outputMap}; - - SmallVector combinerOps; - matchReduction(linalgOp.getRegionOutputArgs(), 0, combinerOps); - Operation *reductionOp = combinerOps[0]; - auto reduction = b.create( - loc, op->getResultTypes(), ValueRange({partialReduce[0]}), - linalgOp.getDpsInits(), reductionMaps, reductionIteratorTypes, - [reductionOp](OpBuilder &b, Location loc, ValueRange inputs) { - Operation *clonedReductionOp = b.clone(*reductionOp); - clonedReductionOp->setOperand(0, inputs[0]); - clonedReductionOp->setOperand(1, inputs[1]); - b.create(loc, clonedReductionOp->getResult(0)); + loc, op->getResultTypes(), partialReduce, linalgOp.getDpsInits(), + indexingMaps, iterators, + [&linalgOp](OpBuilder &b, Location loc, ValueRange inputs) { + int64_t numInits = linalgOp.getNumDpsInits(); + SmallVector yieldedValues; + for (int idx : llvm::seq(0, numInits)) { + // Get the combiner op. + SmallVector combinerOps; + matchReduction(linalgOp.getRegionOutputArgs(), idx, combinerOps); + Operation *clonedReductionOp = b.clone(*combinerOps[0]); + // Combine the input at idx and output at numInits + idx. + clonedReductionOp->setOperand(0, inputs[idx]); + clonedReductionOp->setOperand(1, inputs[numInits + idx]); + // Yield. + yieldedValues.push_back(clonedReductionOp->getResult(0)); + } + b.create(loc, yieldedValues); }); return reduction.getOperation(); } diff --git a/mlir/lib/Dialect/SCF/Transforms/TileUsingInterface.cpp b/mlir/lib/Dialect/SCF/Transforms/TileUsingInterface.cpp index 1a84a59ddb69..a72dafe72517 100644 --- a/mlir/lib/Dialect/SCF/Transforms/TileUsingInterface.cpp +++ b/mlir/lib/Dialect/SCF/Transforms/TileUsingInterface.cpp @@ -182,6 +182,9 @@ static LogicalResult generateLoopNestUsingForOp( if (loops.empty()) return success(); + assert(tiledResults.size() == destinationTensors.size() && + "Number of results of body should be equal to number of iter args"); + // 6. Yield all the results of the tiled operation. SmallVector yieldedValues; for (auto [tiledValue, destinationTensor, resultOffset, resultSize] : @@ -694,9 +697,6 @@ mlir::scf::tileReductionUsingScf(RewriterBase &b, tileSizesVector.append(iterationDomain.size() - tileSizesVector.size(), zero); } - if (op->getNumResults() != 1) - return b.notifyMatchFailure( - op, "don't support ops with multiple results for now"); SmallVector iterators = tilingInterfaceOp.getLoopIteratorTypes(); @@ -708,12 +708,13 @@ mlir::scf::tileReductionUsingScf(RewriterBase &b, } // 2. create the inital tensor value. - FailureOr identityTensor = + FailureOr> maybeInitTensors = op.generateInitialTensorForPartialReduction(b, loc, tileSizesVector, reductionDims); - if (failed(identityTensor)) - return b.notifyMatchFailure(op, - "cannot create a tensor of identity value."); + if (failed(maybeInitTensors)) { + return b.notifyMatchFailure(op, "Failed to create initial tensors."); + } + SmallVector &initTensors = maybeInitTensors.value(); // 3. Define the callback to use for generating the inner most tile loop body. Operation *parallelOp = nullptr; @@ -753,29 +754,26 @@ mlir::scf::tileReductionUsingScf(RewriterBase &b, tiledResult.append(parallelOp->result_begin(), parallelOp->result_end()); // 4d. Compute the offsets and sizes needed to insert the result of the // tiled value back into destination before yielding the destination. - SmallVector outOffsets(offsets.size(), b.getIndexAttr(0)); - resultOffsets.emplace_back(std::move(outOffsets)); - - SmallVector outSizes; - for (size_t i = 0; i < offsets.size(); i++) { - outSizes.push_back( - tensor::getMixedSize(b, loc, parallelOp->getResult(0), i)); + for (int resultIdx : llvm::seq(0, parallelOp->getNumResults())) { + SmallVector outOffsets(offsets.size(), b.getIndexAttr(0)); + resultOffsets.emplace_back(std::move(outOffsets)); + + SmallVector outSizes; + for (size_t i = 0; i < offsets.size(); i++) { + outSizes.push_back( + tensor::getMixedSize(b, loc, parallelOp->getResult(resultIdx), i)); + } + resultSizes.emplace_back(std::move(outSizes)); } - resultSizes.emplace_back(std::move(outSizes)); return success(); }; // 5. Generate the tiled implementation using the destination tensors. - SmallVector destinationTensors = - llvm::map_to_vector(identityTensor.value()->getResults(), - [](OpResult res) -> Value { return res; }); - SmallVector loops; scf::SCFTilingOptions options; options.setLoopType(scf::SCFTilingOptions::LoopType::ForOp); if (failed(generateLoopNest(b, loc, options, iterationDomain, tileSizesVector, - destinationTensors, innerYieldTiledValuesFn, - loops))) + initTensors, innerYieldTiledValuesFn, loops))) return b.notifyMatchFailure(op, "failed to tile for parallel reduction"); SmallVector replacements = llvm::map_to_vector( @@ -787,7 +785,7 @@ mlir::scf::tileReductionUsingScf(RewriterBase &b, b.replaceOp(op, mergeOp->getResults()); SCFReductionTilingResult results; - results.initialOp = *identityTensor; + results.initialValues = initTensors; results.loops = loops; results.parallelTiledOp = parallelOp; results.mergeOp = mergeOp; diff --git a/mlir/test/Dialect/Linalg/transform-tile-reduction.mlir b/mlir/test/Dialect/Linalg/transform-tile-reduction.mlir index 0e1512717a22..f3cf7c4dffa0 100644 --- a/mlir/test/Dialect/Linalg/transform-tile-reduction.mlir +++ b/mlir/test/Dialect/Linalg/transform-tile-reduction.mlir @@ -80,13 +80,14 @@ module attributes {transform.with_named_sequence} { // CHECK-DAG: #[[MAP0:.*]] = affine_map<(d0)[s0] -> (-d0 + s0, 5)> // CHECK-DAG: #[[MAP1:.*]] = affine_map<(d0, d1) -> (d0, d1)> -// CHECK-DAG: #[[MAP2:.*]] = affine_map<(d0, d1) -> (d1)> +// CHECK-DAG: #[[MAP2:.*]] = affine_map<(d0, d1) -> (d1, d0)> +// CHECK-DAG: #[[MAP3:.*]] = affine_map<(d0, d1) -> (d1)> // CHECK: func @reduction_tile_transpose // CHECK: tensor.empty(%{{.*}}) : tensor<5x?xf32> // CHECK: linalg.fill {{.*}} : tensor<5x?xf32>) -> tensor<5x?xf32> // CHECK: scf.for // CHECK: %[[EXT:.*]] = tensor.extract_slice %[[ARG3:.*]][0, 0] [%[[D0:.*]], %[[D1:.*]]] [1, 1] : tensor<5x?xf32> to tensor -// CHECK: %[[R:.*]] = linalg.generic {indexing_maps = [#[[MAP1]], #[[MAP1]]], iterator_types = ["parallel", "parallel"]} ins(%[[L:.*]] : tensor) outs(%[[EXT]] : tensor) +// CHECK: %[[R:.*]] = linalg.generic {indexing_maps = [#[[MAP1]], #[[MAP2]]], iterator_types = ["parallel", "parallel"]} ins(%[[L:.*]] : tensor) outs(%[[EXT]] : tensor) // CHECK: %[[INS:.*]] = tensor.insert_slice %[[R]] into %[[ARG3]][0, 0] [%[[D0]], %[[D1]]] [1, 1] : tensor into tensor<5x?xf32> // CHECK: scf.yield {{.*}} : tensor<5x?xf32> // CHECK: } @@ -403,3 +404,48 @@ module { // CHECK: scf.yield %[[L1]] : tensor<4096x2x64xf32> // CHECK: %[[OUT2:.*]] = linalg.generic {indexing_maps = [{{.*}}, {{.*}}], iterator_types = ["parallel", "reduction", "reduction"]} ins(%{{.*}} : tensor<4096x2x64xf32>) outs(%{{.*}} : tensor<4096xf32>) // CHECK: return %[[OUT2]] : tensor<4096xf32> + +// ----- + +func.func @reduction_tile_multiple_results(%arg0: tensor, %out: tensor, %out2: tensor) -> (tensor, tensor) { + %red:2 = linalg.generic {indexing_maps = [affine_map<(d0, d1) -> (d0, d1)>, + affine_map<(d0, d1) -> (d0)>, + affine_map<(d0, d1) -> (d0)>], + iterator_types = ["parallel", "reduction"]} + ins(%arg0 : tensor) + outs(%out, %out2 : tensor, tensor) { + ^bb0(%arg7: f32, %arg9: f32, %arg9_1: f32): + %1 = arith.mulf %arg7, %arg7 : f32 + %2 = arith.addf %1, %arg9 : f32 + %3 = arith.maximumf %1, %arg9_1 : f32 + linalg.yield %2, %3 : f32, f32 + } -> (tensor, tensor) + return %red#0, %red#1 : tensor, tensor +} + +module attributes {transform.with_named_sequence} { + transform.named_sequence @__transform_main(%arg1: !transform.any_op {transform.readonly}) { + %0 = transform.structured.match ops{["linalg.generic"]} in %arg1 : (!transform.any_op) -> !transform.any_op + %1, %12, %2, %3, %loop = transform.structured.tile_reduction_using_for %0 + by tile_sizes = [0, 5] : (!transform.any_op) -> (!transform.any_op, !transform.any_op, !transform.any_op, !transform.any_op, !transform.any_op) + transform.yield + } +} + +// CHECK: func @reduction_tile_multiple_results +// CHECK-DAG: %[[SUM_ID:.+]] = arith.constant 0.000000e+00 : f32 +// CHECK-DAG: %[[MAX_ID:.+]] = arith.constant 0xFF800000 : f32 +// CHECK-DAG: %[[SUM_INIT:.+]] = linalg.fill ins(%[[SUM_ID]] : f32) outs(%{{.*}} : tensor) -> tensor +// CHECK-DAG: %[[MAX_INIT:.+]] = linalg.fill ins(%[[MAX_ID]] : f32) outs(%{{.*}} : tensor) -> tensor +// CHECK: %[[OUT:.+]]:2 = scf.for +// CHECK-SAME: iter_args(%[[SUM:.+]] = %[[SUM_INIT]], %[[MAX:.+]] = %[[MAX_INIT]]) +// CHECK: %[[UPDATED:.*]]:2 = linalg.generic +// CHECK: arith.mulf +// CHECK: arith.addf +// CHECK: arith.maximumf +// CHECK: %[[INSERT1:.+]] = tensor.insert_slice %[[UPDATED]]#0 into %[[SUM]] +// CHECK: %[[INSERT2:.+]] = tensor.insert_slice %[[UPDATED]]#1 into %[[MAX]] +// CHECK: scf.yield %[[INSERT1]], %[[INSERT1]] +// CHECK: linalg.generic +// CHECK: arith.addf +// CHECK: arith.maximumf -- GitLab From da88e7fbd74cef33411bb5115f20e4b474d2d8b1 Mon Sep 17 00:00:00 2001 From: Sirraide Date: Wed, 22 May 2024 20:27:26 +0200 Subject: [PATCH 174/452] [Clang] Remove parameter that shouldn't be there (#93086) The parameter of `getAddress()` was not being used, as I recall, and seems to have been removed in the meantime. Merging this w/o review since this is breaking builds. --- clang/lib/CodeGen/CGExpr.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp index 4c4a42134dd4..407202537676 100644 --- a/clang/lib/CodeGen/CGExpr.cpp +++ b/clang/lib/CodeGen/CGExpr.cpp @@ -4701,7 +4701,7 @@ LValue CodeGenFunction::EmitLValueForLambdaField(const FieldDecl *Field, if (ThisTy != LambdaTy) { const CXXCastPath &BasePathArray = getContext().LambdaCastPaths.at(MD); Address Base = GetAddressOfBaseClass( - LambdaLV.getAddress(*this), ThisTy, BasePathArray.begin(), + LambdaLV.getAddress(), ThisTy, BasePathArray.begin(), BasePathArray.end(), /*NullCheckValue=*/false, SourceLocation()); LambdaLV = MakeAddrLValue(Base, QualType{LambdaTy->getTypeForDecl(), 0}); } -- GitLab From 8baf96f3060bc26a308b3614feed4117e5299d3c Mon Sep 17 00:00:00 2001 From: Daniel Thornburgh Date: Wed, 22 May 2024 13:27:55 -0500 Subject: [PATCH 175/452] Revert "[IR] Avoid creating icmp/fcmp constant expressions" (#93087) Reverts llvm/llvm-project#92885 due to LLDB CI breakages. --- clang/test/Analysis/builtin_signbit.cpp | 36 +++--- .../catch-nullptr-and-nonzero-offset.c | 62 ++++------- clang/test/CodeGen/constantexpr-fneg.c | 3 +- clang/test/CodeGenCXX/cxx11-thread-local.cpp | 20 ++-- .../test/CodeGenCXX/ubsan-nullability-arg.cpp | 3 +- clang/test/CodeGenCXX/weak-external.cpp | 15 +-- clang/test/Driver/linker-wrapper-image.c | 98 ++++++++--------- clang/test/OpenMP/threadprivate_codegen.cpp | 104 ++++++++---------- llvm/include/llvm/Analysis/TargetFolder.h | 2 +- llvm/include/llvm/IR/ConstantFolder.h | 2 +- llvm/lib/Analysis/ConstantFolding.cpp | 2 +- llvm/lib/IR/ConstantFold.cpp | 13 +-- llvm/test/Assembler/ConstantExprFold.ll | 4 +- llvm/test/Assembler/ConstantExprNoFold.ll | 4 +- llvm/test/Assembler/vector-cmp.ll | 2 +- .../AMDGPU/lower-ctor-dtor-constexpr-alias.ll | 3 +- llvm/test/CodeGen/AMDGPU/lower-ctor-dtor.ll | 3 +- .../AMDGPU/lower-multiple-ctor-dtor.ll | 3 +- .../MemorySanitizer/check-constant-shadow.ll | 3 +- .../SanitizerBinaryMetadata/atomics.ll | 12 +- .../Transforms/Attributor/value-simplify.ll | 7 +- .../binop-select-cast-of-select-cond.ll | 2 +- .../constant-fold-address-space-pointer.ll | 6 +- .../Transforms/InstCombine/getelementptr.ll | 3 +- ...hoist-xor-by-constant-from-xor-by-value.ll | 3 +- llvm/test/Transforms/InstCombine/pr33453.ll | 2 +- llvm/test/Transforms/InstCombine/pr83947.ll | 4 +- llvm/test/Transforms/InstCombine/rem.ll | 4 +- .../Transforms/InstCombine/select-and-or.ll | 4 +- .../InstCombine/select-safe-transforms.ll | 4 +- .../InstSimplify/ConstProp/bitcast.ll | 9 +- .../InstSimplify/ConstProp/icmp-global.ll | 54 +++------ .../InstSimplify/bitcast-vector-fold.ll | 3 +- llvm/test/Transforms/InstSimplify/compare.ll | 6 +- .../Transforms/InstSimplify/past-the-end.ll | 6 +- .../JumpThreading/constant-fold-status.ll | 3 +- .../LowerTypeTests/cfi-direct-call1.ll | 10 +- .../LowerTypeTests/function-weak.ll | 74 ++++++------- .../test/Transforms/SCCP/conditions-ranges.ll | 9 +- .../phi-to-select-constexpr-icmp.ll | 2 +- 40 files changed, 256 insertions(+), 353 deletions(-) diff --git a/clang/test/Analysis/builtin_signbit.cpp b/clang/test/Analysis/builtin_signbit.cpp index be10f0950f69..57e6816ce280 100644 --- a/clang/test/Analysis/builtin_signbit.cpp +++ b/clang/test/Analysis/builtin_signbit.cpp @@ -84,30 +84,28 @@ long double ld = -1.0L; // CHECK-LE-LABEL: define dso_local void @_Z12test_signbitv( // CHECK-LE-SAME: ) #[[ATTR0:[0-9]+]] { // CHECK-LE-NEXT: entry: -// CHECK-LE-NEXT: [[TMP0:%.*]] = icmp slt i64 trunc (i128 bitcast (ppc_fp128 0xM3FF00000000000000000000000000000 to i128) to i64), 0 -// CHECK-LE-NEXT: [[FROMBOOL:%.*]] = zext i1 [[TMP0]] to i8 +// CHECK-LE-NEXT: [[FROMBOOL:%.*]] = zext i1 icmp slt (i64 trunc (i128 bitcast (ppc_fp128 0xM3FF00000000000000000000000000000 to i128) to i64), i64 0) to i8 // CHECK-LE-NEXT: store i8 [[FROMBOOL]], ptr @b, align 1 -// CHECK-LE-NEXT: [[TMP1:%.*]] = load ppc_fp128, ptr @ld, align 16 -// CHECK-LE-NEXT: [[TMP2:%.*]] = bitcast ppc_fp128 [[TMP1]] to i128 -// CHECK-LE-NEXT: [[TMP3:%.*]] = trunc i128 [[TMP2]] to i64 -// CHECK-LE-NEXT: [[TMP4:%.*]] = icmp slt i64 [[TMP3]], 0 -// CHECK-LE-NEXT: [[FROMBOOL1:%.*]] = zext i1 [[TMP4]] to i8 +// CHECK-LE-NEXT: [[TMP0:%.*]] = load ppc_fp128, ptr @ld, align 16 +// CHECK-LE-NEXT: [[TMP1:%.*]] = bitcast ppc_fp128 [[TMP0]] to i128 +// CHECK-LE-NEXT: [[TMP2:%.*]] = trunc i128 [[TMP1]] to i64 +// CHECK-LE-NEXT: [[TMP3:%.*]] = icmp slt i64 [[TMP2]], 0 +// CHECK-LE-NEXT: [[FROMBOOL1:%.*]] = zext i1 [[TMP3]] to i8 // CHECK-LE-NEXT: store i8 [[FROMBOOL1]], ptr @b, align 1 // CHECK-LE-NEXT: store i8 0, ptr @b, align 1 -// CHECK-LE-NEXT: [[TMP5:%.*]] = load double, ptr @d, align 8 -// CHECK-LE-NEXT: [[CONV:%.*]] = fptrunc double [[TMP5]] to float -// CHECK-LE-NEXT: [[TMP6:%.*]] = bitcast float [[CONV]] to i32 -// CHECK-LE-NEXT: [[TMP7:%.*]] = icmp slt i32 [[TMP6]], 0 -// CHECK-LE-NEXT: [[FROMBOOL2:%.*]] = zext i1 [[TMP7]] to i8 +// CHECK-LE-NEXT: [[TMP4:%.*]] = load double, ptr @d, align 8 +// CHECK-LE-NEXT: [[CONV:%.*]] = fptrunc double [[TMP4]] to float +// CHECK-LE-NEXT: [[TMP5:%.*]] = bitcast float [[CONV]] to i32 +// CHECK-LE-NEXT: [[TMP6:%.*]] = icmp slt i32 [[TMP5]], 0 +// CHECK-LE-NEXT: [[FROMBOOL2:%.*]] = zext i1 [[TMP6]] to i8 // CHECK-LE-NEXT: store i8 [[FROMBOOL2]], ptr @b, align 1 -// CHECK-LE-NEXT: [[TMP8:%.*]] = icmp slt i64 trunc (i128 bitcast (ppc_fp128 0xM3FF00000000000000000000000000000 to i128) to i64), 0 -// CHECK-LE-NEXT: [[FROMBOOL3:%.*]] = zext i1 [[TMP8]] to i8 +// CHECK-LE-NEXT: [[FROMBOOL3:%.*]] = zext i1 icmp slt (i64 trunc (i128 bitcast (ppc_fp128 0xM3FF00000000000000000000000000000 to i128) to i64), i64 0) to i8 // CHECK-LE-NEXT: store i8 [[FROMBOOL3]], ptr @b, align 1 -// CHECK-LE-NEXT: [[TMP9:%.*]] = load ppc_fp128, ptr @ld, align 16 -// CHECK-LE-NEXT: [[TMP10:%.*]] = bitcast ppc_fp128 [[TMP9]] to i128 -// CHECK-LE-NEXT: [[TMP11:%.*]] = trunc i128 [[TMP10]] to i64 -// CHECK-LE-NEXT: [[TMP12:%.*]] = icmp slt i64 [[TMP11]], 0 -// CHECK-LE-NEXT: [[FROMBOOL4:%.*]] = zext i1 [[TMP12]] to i8 +// CHECK-LE-NEXT: [[TMP7:%.*]] = load ppc_fp128, ptr @ld, align 16 +// CHECK-LE-NEXT: [[TMP8:%.*]] = bitcast ppc_fp128 [[TMP7]] to i128 +// CHECK-LE-NEXT: [[TMP9:%.*]] = trunc i128 [[TMP8]] to i64 +// CHECK-LE-NEXT: [[TMP10:%.*]] = icmp slt i64 [[TMP9]], 0 +// CHECK-LE-NEXT: [[FROMBOOL4:%.*]] = zext i1 [[TMP10]] to i8 // CHECK-LE-NEXT: store i8 [[FROMBOOL4]], ptr @b, align 1 // CHECK-LE-NEXT: ret void // diff --git a/clang/test/CodeGen/catch-nullptr-and-nonzero-offset.c b/clang/test/CodeGen/catch-nullptr-and-nonzero-offset.c index e93dbcb9f647..015102940890 100644 --- a/clang/test/CodeGen/catch-nullptr-and-nonzero-offset.c +++ b/clang/test/CodeGen/catch-nullptr-and-nonzero-offset.c @@ -217,10 +217,8 @@ char *nullptr_zero(void) { char *nullptr_one_BAD(void) { // CHECK: define{{.*}} ptr @nullptr_one_BAD() // CHECK-NEXT: [[ENTRY:.*]]: - // CHECK-SANITIZE-NEXT: %[[CMP:.*]] = icmp ne i64 ptrtoint (ptr getelementptr inbounds (i8, ptr null, i64 1) to i64), 0, !nosanitize - // CHECK-SANITIZE-C-NEXT: %[[COND:.*]] = and i1 false, %[[CMP]], !nosanitize - // CHECK-SANITIZE-CPP-NEXT: %[[COND:.*]] = icmp eq i1 false, %[[CMP]], !nosanitize - // CHECK-SANITIZE-NEXT: br i1 %[[COND]], label %[[CONT:.*]], label %[[HANDLER_POINTER_OVERFLOW:[^,]+]],{{.*}} !nosanitize + // CHECK-SANITIZE-C-NEXT: br i1 false, label %[[CONT:.*]], label %[[HANDLER_POINTER_OVERFLOW:[^,]+]],{{.*}} !nosanitize + // CHECK-SANITIZE-CPP-NEXT: br i1 icmp eq (i64 ptrtoint (ptr getelementptr inbounds (i8, ptr null, i64 1) to i64), i64 0), label %[[CONT:.*]], label %[[HANDLER_POINTER_OVERFLOW:[^,]+]],{{.*}} !nosanitize // CHECK-SANITIZE: [[HANDLER_POINTER_OVERFLOW]]: // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_pointer_overflow_abort(ptr @[[LINE_700]], i64 0, i64 ptrtoint (ptr getelementptr inbounds (i8, ptr null, i64 1) to i64)) // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_pointer_overflow(ptr @[[LINE_700]], i64 0, i64 ptrtoint (ptr getelementptr inbounds (i8, ptr null, i64 1) to i64)) @@ -237,10 +235,8 @@ char *nullptr_one_BAD(void) { char *nullptr_allones_BAD(void) { // CHECK: define{{.*}} ptr @nullptr_allones_BAD() // CHECK-NEXT: [[ENTRY:.*]]: - // CHECK-SANITIZE-NEXT: %[[CMP:.*]] = icmp ne i64 ptrtoint (ptr getelementptr inbounds (i8, ptr null, i64 -1) to i64), 0, !nosanitize - // CHECK-SANITIZE-C-NEXT: %[[COND:.*]] = and i1 false, %[[CMP]], !nosanitize - // CHECK-SANITIZE-CPP-NEXT: %[[COND:.*]] = icmp eq i1 false, %[[CMP]], !nosanitize - // CHECK-SANITIZE-NEXT: br i1 %[[COND]], label %[[CONT:.*]], label %[[HANDLER_POINTER_OVERFLOW:[^,]+]],{{.*}} !nosanitize + // CHECK-SANITIZE-C-NEXT: br i1 false, label %[[CONT:.*]], label %[[HANDLER_POINTER_OVERFLOW:[^,]+]],{{.*}} !nosanitize + // CHECK-SANITIZE-CPP-NEXT: br i1 icmp eq (i64 ptrtoint (ptr getelementptr inbounds (i8, ptr null, i64 -1) to i64), i64 0), label %[[CONT:.*]], label %[[HANDLER_POINTER_OVERFLOW:[^,]+]],{{.*}} !nosanitize // CHECK-SANITIZE: [[HANDLER_POINTER_OVERFLOW]]: // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_pointer_overflow_abort(ptr @[[LINE_800]], i64 0, i64 ptrtoint (ptr getelementptr inbounds (i8, ptr null, i64 -1) to i64)) // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_pointer_overflow(ptr @[[LINE_800]], i64 0, i64 ptrtoint (ptr getelementptr inbounds (i8, ptr null, i64 -1) to i64)) @@ -268,10 +264,9 @@ char *one_var(unsigned long offset) { // CHECK-SANITIZE-NEXT: %[[OR_OV:.+]] = or i1 %[[COMPUTED_OFFSET_OVERFLOWED]], false, !nosanitize // CHECK-SANITIZE-NEXT: %[[COMPUTED_OFFSET:.*]] = extractvalue { i64, i1 } %[[COMPUTED_OFFSET_AGGREGATE]], 0, !nosanitize // CHECK-SANITIZE-NEXT: %[[COMPUTED_GEP:.*]] = add i64 1, %[[COMPUTED_OFFSET]], !nosanitize - // CHECK-SANITIZE-NEXT: %[[OTHER_IS_NOT_NULL:.*]] = icmp ne ptr inttoptr (i64 1 to ptr), null // CHECK-SANITIZE-NEXT: %[[COMPUTED_GEP_IS_NOT_NULL:.*]] = icmp ne i64 %[[COMPUTED_GEP]], 0, !nosanitize - // CHECK-SANITIZE-C-NEXT: %[[BOTH_POINTERS_ARE_NULL_OR_BOTH_ARE_NONNULL:.*]] = and i1 %[[OTHER_IS_NOT_NULL]], %[[COMPUTED_GEP_IS_NOT_NULL]], !nosanitize - // CHECK-SANITIZE-CPP-NEXT: %[[BOTH_POINTERS_ARE_NULL_OR_BOTH_ARE_NONNULL:.*]] = icmp eq i1 %[[OTHER_IS_NOT_NULL]], %[[COMPUTED_GEP_IS_NOT_NULL]], !nosanitize + // CHECK-SANITIZE-C-NEXT: %[[BOTH_POINTERS_ARE_NULL_OR_BOTH_ARE_NONNULL:.*]] = and i1 icmp ne (ptr inttoptr (i64 1 to ptr), ptr null), %[[COMPUTED_GEP_IS_NOT_NULL]], !nosanitize + // CHECK-SANITIZE-CPP-NEXT: %[[BOTH_POINTERS_ARE_NULL_OR_BOTH_ARE_NONNULL:.*]] = icmp eq i1 icmp ne (ptr inttoptr (i64 1 to ptr), ptr null), %[[COMPUTED_GEP_IS_NOT_NULL]], !nosanitize // CHECK-SANITIZE-NEXT: %[[COMPUTED_OFFSET_DID_NOT_OVERFLOW:.*]] = xor i1 %[[OR_OV]], true, !nosanitize // CHECK-SANITIZE-NEXT: %[[COMPUTED_GEP_IS_UGE_BASE:.*]] = icmp uge i64 %[[COMPUTED_GEP]], 1, !nosanitize // CHECK-SANITIZE-NEXT: %[[GEP_DID_NOT_OVERFLOW:.*]] = and i1 %[[COMPUTED_GEP_IS_UGE_BASE]], %[[COMPUTED_OFFSET_DID_NOT_OVERFLOW]], !nosanitize @@ -292,9 +287,7 @@ char *one_var(unsigned long offset) { char *one_zero(void) { // CHECK: define{{.*}} ptr @one_zero() // CHECK-NEXT: [[ENTRY:.*]]: - // CHECK-SANITIZE-C-NEXT: %[[CMP:.*]] = icmp ne ptr inttoptr (i64 1 to ptr), null - // CHECK-SANITIZE-C-NEXT: %[[AND:.*]] = and i1 %[[CMP]], true - // CHECK-SANITIZE-C-NEXT: br i1 %[[AND]], label %[[CONT:.*]], label %[[HANDLER_POINTER_OVERFLOW:[^,]+]],{{.*}} !nosanitize + // CHECK-SANITIZE-C-NEXT: br i1 icmp ne (ptr inttoptr (i64 1 to ptr), ptr null), label %[[CONT:.*]], label %[[HANDLER_POINTER_OVERFLOW:[^,]+]],{{.*}} !nosanitize // CHECK-SANITIZE-C: [[HANDLER_POINTER_OVERFLOW]]: // CHECK-SANITIZE-NORECOVER-C-NEXT: call void @__ubsan_handle_pointer_overflow_abort(ptr @[[LINE_1000]], i64 1, i64 1) // CHECK-SANITIZE-RECOVER-C-NEXT: call void @__ubsan_handle_pointer_overflow(ptr @[[LINE_1000]], i64 1, i64 1) @@ -311,11 +304,9 @@ char *one_zero(void) { char *one_one_OK(void) { // CHECK: define{{.*}} ptr @one_one_OK() // CHECK-NEXT: [[ENTRY:.*]]: - // CHECK-SANITIZE-NEXT: %[[CMP1:.*]] = icmp ne ptr inttoptr (i64 1 to ptr), null, !nosanitize - // CHECK-SANITIZE-NEXT: %[[CMP2:.*]] = icmp ne i64 add (i64 sub (i64 ptrtoint (ptr getelementptr inbounds (i8, ptr inttoptr (i64 1 to ptr), i64 1) to i64), i64 1), i64 1), 0, !nosanitize - // CHECK-SANITIZE-C-NEXT: %[[COND:.*]] = and i1 %[[CMP1]], %[[CMP2]], !nosanitize - // CHECK-SANITIZE-CPP-NEXT: %[[COND:.*]] = icmp eq i1 %[[CMP1]], %[[CMP2]], !nosanitize - // CHECK-SANITIZE-NEXT: br i1 %[[COND]], label %[[CONT:.*]], label %[[HANDLER_POINTER_OVERFLOW:[^,]+]],{{.*}} !nosanitize + // CHECK-SANITIZE-C-NEXT: %[[AND:.*]] = and i1 icmp ne (ptr inttoptr (i64 1 to ptr), ptr null), icmp ne (i64 add (i64 sub (i64 ptrtoint (ptr getelementptr inbounds (i8, ptr inttoptr (i64 1 to ptr), i64 1) to i64), i64 1), i64 1), i64 0), !nosanitize + // CHECK-SANITIZE-C-NEXT: br i1 %[[AND]], label %[[CONT:.*]], label %[[HANDLER_POINTER_OVERFLOW:[^,]+]],{{.*}} !nosanitize + // CHECK-SANITIZE-CPP-NEXT: br i1 xor (i1 icmp eq (ptr inttoptr (i64 1 to ptr), ptr null), i1 icmp ne (i64 add (i64 sub (i64 ptrtoint (ptr getelementptr inbounds (i8, ptr inttoptr (i64 1 to ptr), i64 1) to i64), i64 1), i64 1), i64 0)), label %[[CONT:.*]], label %[[HANDLER_POINTER_OVERFLOW:[^,]+]],{{.*}} !nosanitize // CHECK-SANITIZE: [[HANDLER_POINTER_OVERFLOW]]: // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_pointer_overflow_abort(ptr @[[LINE_1100]], i64 1, i64 add (i64 sub (i64 ptrtoint (ptr getelementptr inbounds (i8, ptr inttoptr (i64 1 to ptr), i64 1) to i64), i64 1), i64 1)) // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_pointer_overflow(ptr @[[LINE_1100]], i64 1, i64 add (i64 sub (i64 ptrtoint (ptr getelementptr inbounds (i8, ptr inttoptr (i64 1 to ptr), i64 1) to i64), i64 1), i64 1)) @@ -332,11 +323,9 @@ char *one_one_OK(void) { char *one_allones_BAD(void) { // CHECK: define{{.*}} ptr @one_allones_BAD() // CHECK-NEXT: [[ENTRY:.*]]: - // CHECK-SANITIZE-NEXT: %[[CMP1:.*]] = icmp ne ptr inttoptr (i64 1 to ptr), null, !nosanitize - // CHECK-SANITIZE-NEXT: %[[CMP2:.*]] = icmp ne i64 add (i64 sub (i64 ptrtoint (ptr getelementptr inbounds (i8, ptr inttoptr (i64 1 to ptr), i64 -1) to i64), i64 1), i64 1), 0, !nosanitize - // CHECK-SANITIZE-C-NEXT: %[[COND:.*]] = and i1 %[[CMP1]], %[[CMP2]], !nosanitize - // CHECK-SANITIZE-CPP-NEXT: %[[COND:.*]] = icmp eq i1 %[[CMP1]], %[[CMP2]], !nosanitize - // CHECK-SANITIZE-NEXT: br i1 %[[COND]], label %[[CONT:.*]], label %[[HANDLER_POINTER_OVERFLOW:[^,]+]],{{.*}} !nosanitize + // CHECK-SANITIZE-C-NEXT: %[[AND:.*]] = and i1 icmp ne (ptr inttoptr (i64 1 to ptr), ptr null), icmp ne (i64 add (i64 sub (i64 ptrtoint (ptr getelementptr inbounds (i8, ptr inttoptr (i64 1 to ptr), i64 -1) to i64), i64 1), i64 1), i64 0), !nosanitize + // CHECK-SANITIZE-C-NEXT: br i1 %[[AND]], label %[[CONT:.*]], label %[[HANDLER_POINTER_OVERFLOW:[^,]+]],{{.*}} !nosanitize + // CHECK-SANITIZE-CPP-NEXT: br i1 xor (i1 icmp eq (ptr inttoptr (i64 1 to ptr), ptr null), i1 icmp ne (i64 add (i64 sub (i64 ptrtoint (ptr getelementptr inbounds (i8, ptr inttoptr (i64 1 to ptr), i64 -1) to i64), i64 1), i64 1), i64 0)), label %[[CONT:.*]], label %[[HANDLER_POINTER_OVERFLOW:[^,]+]],{{.*}} !nosanitize // CHECK-SANITIZE: [[HANDLER_POINTER_OVERFLOW]]: // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_pointer_overflow_abort(ptr @[[LINE_1200]], i64 1, i64 add (i64 sub (i64 ptrtoint (ptr getelementptr inbounds (i8, ptr inttoptr (i64 1 to ptr), i64 -1) to i64), i64 1), i64 1)) // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_pointer_overflow(ptr @[[LINE_1200]], i64 1, i64 add (i64 sub (i64 ptrtoint (ptr getelementptr inbounds (i8, ptr inttoptr (i64 1 to ptr), i64 -1) to i64), i64 1), i64 1)) @@ -364,10 +353,9 @@ char *allones_var(unsigned long offset) { // CHECK-SANITIZE-NEXT: %[[OR_OV:.+]] = or i1 %[[COMPUTED_OFFSET_OVERFLOWED]], false, !nosanitize // CHECK-SANITIZE-NEXT: %[[COMPUTED_OFFSET:.*]] = extractvalue { i64, i1 } %[[COMPUTED_OFFSET_AGGREGATE]], 0, !nosanitize // CHECK-SANITIZE-NEXT: %[[COMPUTED_GEP:.*]] = add i64 -1, %[[COMPUTED_OFFSET]], !nosanitize - // CHECK-SANITIZE-NEXT: %[[OTHER_IS_NOT_NULL:.*]] = icmp ne ptr inttoptr (i64 -1 to ptr), null, !nosanitize // CHECK-SANITIZE-NEXT: %[[COMPUTED_GEP_IS_NOT_NULL:.*]] = icmp ne i64 %[[COMPUTED_GEP]], 0, !nosanitize - // CHECK-SANITIZE-C-NEXT: %[[BOTH_POINTERS_ARE_NULL_OR_BOTH_ARE_NONNULL:.*]] = and i1 %[[OTHER_IS_NOT_NULL]], %[[COMPUTED_GEP_IS_NOT_NULL]], !nosanitize - // CHECK-SANITIZE-CPP-NEXT: %[[BOTH_POINTERS_ARE_NULL_OR_BOTH_ARE_NONNULL:.*]] = icmp eq i1 %[[OTHER_IS_NOT_NULL]], %[[COMPUTED_GEP_IS_NOT_NULL]], !nosanitize + // CHECK-SANITIZE-C-NEXT: %[[BOTH_POINTERS_ARE_NULL_OR_BOTH_ARE_NONNULL:.*]] = and i1 icmp ne (ptr inttoptr (i64 -1 to ptr), ptr null), %[[COMPUTED_GEP_IS_NOT_NULL]], !nosanitize + // CHECK-SANITIZE-CPP-NEXT: %[[BOTH_POINTERS_ARE_NULL_OR_BOTH_ARE_NONNULL:.*]] = icmp eq i1 icmp ne (ptr inttoptr (i64 -1 to ptr), ptr null), %[[COMPUTED_GEP_IS_NOT_NULL]], !nosanitize // CHECK-SANITIZE-NEXT: %[[COMPUTED_OFFSET_DID_NOT_OVERFLOW:.*]] = xor i1 %[[OR_OV]], true, !nosanitize // CHECK-SANITIZE-NEXT: %[[COMPUTED_GEP_IS_UGE_BASE:.*]] = icmp uge i64 %[[COMPUTED_GEP]], -1, !nosanitize // CHECK-SANITIZE-NEXT: %[[GEP_DID_NOT_OVERFLOW:.*]] = and i1 %[[COMPUTED_GEP_IS_UGE_BASE]], %[[COMPUTED_OFFSET_DID_NOT_OVERFLOW]], !nosanitize @@ -388,9 +376,7 @@ char *allones_var(unsigned long offset) { char *allones_zero_OK(void) { // CHECK: define{{.*}} ptr @allones_zero_OK() // CHECK-NEXT: [[ENTRY:.*]]: - // CHECK-SANITIZE-C-NEXT: %[[CMP:.*]] = icmp ne ptr inttoptr (i64 -1 to ptr), null, !nosanitize - // CHECK-SANITIZE-C-NEXT: %[[AND:.*]] = and i1 %[[CMP]], true, !nosanitize - // CHECK-SANITIZE-C-NEXT: br i1 %[[AND]], label %[[CONT:.*]], label %[[HANDLER_POINTER_OVERFLOW:[^,]+]],{{.*}} !nosanitize + // CHECK-SANITIZE-C-NEXT: br i1 icmp ne (ptr inttoptr (i64 -1 to ptr), ptr null), label %[[CONT:.*]], label %[[HANDLER_POINTER_OVERFLOW:[^,]+]],{{.*}} !nosanitize // CHECK-SANITIZE-C: [[HANDLER_POINTER_OVERFLOW]]: // CHECK-SANITIZE-NORECOVER-C-NEXT: call void @__ubsan_handle_pointer_overflow_abort(ptr @[[LINE_1400]], i64 -1, i64 -1) // CHECK-SANITIZE-RECOVER-C-NEXT: call void @__ubsan_handle_pointer_overflow(ptr @[[LINE_1400]], i64 -1, i64 -1) @@ -407,11 +393,9 @@ char *allones_zero_OK(void) { char *allones_one_BAD(void) { // CHECK: define{{.*}} ptr @allones_one_BAD() // CHECK-NEXT: [[ENTRY:.*]]: - // CHECK-SANITIZE-NEXT: %[[CMP1:.*]] = icmp ne ptr inttoptr (i64 -1 to ptr), null, !nosanitize - // CHECK-SANITIZE-NEXT: %[[CMP2:.*]] = icmp ne i64 add (i64 sub (i64 ptrtoint (ptr getelementptr inbounds (i8, ptr inttoptr (i64 -1 to ptr), i64 1) to i64), i64 -1), i64 -1), 0, !nosanitize - // CHECK-SANITIZE-C-NEXT: %[[COND:.*]] = and i1 %[[CMP1]], %[[CMP2]], !nosanitize - // CHECK-SANITIZE-CPP-NEXT: %[[COND:.*]] = icmp eq i1 %[[CMP1]], %[[CMP2]], !nosanitize - // CHECK-SANITIZE-NEXT: br i1 %[[COND]], label %[[CONT:.*]], label %[[HANDLER_POINTER_OVERFLOW:[^,]+]],{{.*}} !nosanitize + // CHECK-SANITIZE-C-NEXT: %[[AND:.*]] = and i1 icmp ne (ptr inttoptr (i64 -1 to ptr), ptr null), icmp ne (i64 add (i64 sub (i64 ptrtoint (ptr getelementptr inbounds (i8, ptr inttoptr (i64 -1 to ptr), i64 1) to i64), i64 -1), i64 -1), i64 0), !nosanitize + // CHECK-SANITIZE-C-NEXT: br i1 %[[AND]], label %[[CONT:.*]], label %[[HANDLER_POINTER_OVERFLOW:[^,]+]],{{.*}} !nosanitize + // CHECK-SANITIZE-CPP-NEXT: br i1 xor (i1 icmp eq (ptr inttoptr (i64 -1 to ptr), ptr null), i1 icmp ne (i64 add (i64 sub (i64 ptrtoint (ptr getelementptr inbounds (i8, ptr inttoptr (i64 -1 to ptr), i64 1) to i64), i64 -1), i64 -1), i64 0)), label %[[CONT:.*]], label %[[HANDLER_POINTER_OVERFLOW:[^,]+]],{{.*}} !nosanitize // CHECK-SANITIZE: [[HANDLER_POINTER_OVERFLOW]]: // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_pointer_overflow_abort(ptr @[[LINE_1500]], i64 -1, i64 add (i64 sub (i64 ptrtoint (ptr getelementptr inbounds (i8, ptr inttoptr (i64 -1 to ptr), i64 1) to i64), i64 -1), i64 -1)) // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_pointer_overflow(ptr @[[LINE_1500]], i64 -1, i64 add (i64 sub (i64 ptrtoint (ptr getelementptr inbounds (i8, ptr inttoptr (i64 -1 to ptr), i64 1) to i64), i64 -1), i64 -1)) @@ -428,11 +412,9 @@ char *allones_one_BAD(void) { char *allones_allones_OK(void) { // CHECK: define{{.*}} ptr @allones_allones_OK() // CHECK-NEXT: [[ENTRY:.*]]: - // CHECK-SANITIZE-NEXT: %[[CMP1:.*]] = icmp ne ptr inttoptr (i64 -1 to ptr), null, !nosanitize - // CHECK-SANITIZE-NEXT: %[[CMP2:.*]] = icmp ne i64 add (i64 sub (i64 ptrtoint (ptr getelementptr inbounds (i8, ptr inttoptr (i64 -1 to ptr), i64 -1) to i64), i64 -1), i64 -1), 0, !nosanitize - // CHECK-SANITIZE-C-NEXT: %[[COND:.*]] = and i1 %[[CMP1]], %[[CMP2]], !nosanitize - // CHECK-SANITIZE-CPP-NEXT: %[[COND:.*]] = icmp eq i1 %[[CMP1]], %[[CMP2]], !nosanitize - // CHECK-SANITIZE-NEXT: br i1 %[[COND]], label %[[CONT:.*]], label %[[HANDLER_POINTER_OVERFLOW:[^,]+]],{{.*}} !nosanitize + // CHECK-SANITIZE-C-NEXT: %[[AND:.*]] = and i1 icmp ne (ptr inttoptr (i64 -1 to ptr), ptr null), icmp ne (i64 add (i64 sub (i64 ptrtoint (ptr getelementptr inbounds (i8, ptr inttoptr (i64 -1 to ptr), i64 -1) to i64), i64 -1), i64 -1), i64 0), !nosanitize + // CHECK-SANITIZE-C-NEXT: br i1 %[[AND]], label %[[CONT:.*]], label %[[HANDLER_POINTER_OVERFLOW:[^,]+]],{{.*}} !nosanitize + // CHECK-SANITIZE-CPP-NEXT: br i1 xor (i1 icmp eq (ptr inttoptr (i64 -1 to ptr), ptr null), i1 icmp ne (i64 add (i64 sub (i64 ptrtoint (ptr getelementptr inbounds (i8, ptr inttoptr (i64 -1 to ptr), i64 -1) to i64), i64 -1), i64 -1), i64 0)), label %[[CONT:.*]], label %[[HANDLER_POINTER_OVERFLOW:[^,]+]],{{.*}} !nosanitize // CHECK-SANITIZE: [[HANDLER_POINTER_OVERFLOW]]: // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_pointer_overflow_abort(ptr @[[LINE_1600]], i64 -1, i64 add (i64 sub (i64 ptrtoint (ptr getelementptr inbounds (i8, ptr inttoptr (i64 -1 to ptr), i64 -1) to i64), i64 -1), i64 -1)) // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_pointer_overflow(ptr @[[LINE_1600]], i64 -1, i64 add (i64 sub (i64 ptrtoint (ptr getelementptr inbounds (i8, ptr inttoptr (i64 -1 to ptr), i64 -1) to i64), i64 -1), i64 -1)) diff --git a/clang/test/CodeGen/constantexpr-fneg.c b/clang/test/CodeGen/constantexpr-fneg.c index fb7a3d1a6953..3cd4db34f61a 100644 --- a/clang/test/CodeGen/constantexpr-fneg.c +++ b/clang/test/CodeGen/constantexpr-fneg.c @@ -8,8 +8,7 @@ // CHECK: entry: // CHECK-NEXT: %retval = alloca i32 // CHECK-NEXT: store i32 0, ptr %retval -// CHECK-NEXT: [[CMP:%.*]] = icmp ne ptr @b, @a -// CHECK-NEXT: [[ZEXT:%.*]] = zext i1 [[CMP]] to i32 +// CHECK-NEXT: [[ZEXT:%.*]] = zext i1 true to i32 // CHECK-NEXT: [[SITOFP:%.*]] = sitofp i32 [[ZEXT]] to float // CHECK-NEXT: [[LV:%.*]] = load ptr, ptr @c // CHECK-NEXT: store float [[SITOFP]], ptr [[LV]], align 4 diff --git a/clang/test/CodeGenCXX/cxx11-thread-local.cpp b/clang/test/CodeGenCXX/cxx11-thread-local.cpp index bcc490bc32e6..1a6e289c9c2b 100644 --- a/clang/test/CodeGenCXX/cxx11-thread-local.cpp +++ b/clang/test/CodeGenCXX/cxx11-thread-local.cpp @@ -136,9 +136,8 @@ int f() { // CHECK-NEXT: store i32 %{{.*}}, ptr @c, align 4 // LINUX_AIX-LABEL: define linkonce_odr hidden noundef ptr @_ZTW1b() -// LINUX: [[CMP:%.*]] = icmp ne ptr @_ZTH1b, null -// LINUX: br i1 [[CMP]] -// AIX-NOT: [[CMP:%.*]] = icmp ne ptr @_ZTH1b, null +// LINUX: br i1 icmp ne (ptr @_ZTH1b, ptr null), +// AIX-NOT: br i1 icmp ne (ptr @_ZTH1b, ptr null), // not null: // LINUX_AIX: call void @_ZTH1b() // LINUX: br label @@ -220,27 +219,24 @@ int f() { // DARWIN: declare cxx_fast_tlscc noundef ptr @_ZTWN1VIcE1mE() // LINUX_AIX: define linkonce_odr hidden noundef ptr @_ZTWN1VIcE1mE() {{#[0-9]+}}{{( comdat)?}} { -// LINUX: [[CMP:%.*]] = icmp ne ptr @_ZTHN1VIcE1mE, -// LINUX: br i1 [[CMP]] -// AIX-NOT: [[CMP:%.*]] = icmp ne ptr @_ZTHN1VIcE1mE, +// LINUX: br i1 icmp ne (ptr @_ZTHN1VIcE1mE, +// AIX-NOT: br i1 icmp ne (ptr @_ZTHN1VIcE1mE // LINUX_AIX: call void @_ZTHN1VIcE1mE() // LINUX_AIX: [[VEM_ADDR:%.+]] = call align 4 ptr @llvm.threadlocal.address.p0(ptr align 4 @_ZN1VIcE1mE) // LINUX_AIX: ret ptr [[VEM_ADDR]] // DARWIN: declare cxx_fast_tlscc noundef ptr @_ZTWN1WIcE1mE() // LINUX_AIX: define linkonce_odr hidden noundef ptr @_ZTWN1WIcE1mE() {{#[0-9]+}}{{( comdat)?}} { -// LINUX: [[CMP:%.*]] = icmp ne ptr @_ZTHN1WIcE1mE, -// LINUX: br i1 [[CMP]] -// AIX-NOT: [[CMP:%.*]] = icmp ne ptr @_ZTHN1WIcE1mE, +// LINUX: br i1 icmp ne (ptr @_ZTHN1WIcE1mE, +// AIX-NOT: br i1 icmp ne (ptr @_ZTHN1WIcE1mE, // LINUX_AIX: call void @_ZTHN1WIcE1mE() // LINUX_AIX: [[WEM_ADDR:%.+]] = call align 4 ptr @llvm.threadlocal.address.p0(ptr align 4 @_ZN1WIcE1mE) // LINUX_AIX: ret ptr [[WEM_ADDR]] // DARWIN: declare cxx_fast_tlscc {{.*}}ptr @_ZTWN1XIcE1mE() // LINUX_AIX: define linkonce_odr hidden {{.*}}ptr @_ZTWN1XIcE1mE() {{#[0-9]+}}{{( comdat)?}} { -// LINUX: [[CMP:%.*]] = icmp ne ptr @_ZTHN1XIcE1mE, -// LINUX: br i1 [[CMP]] -// AIX-NOT: [[CMP:%.*]] = icmp ne ptr @_ZTHN1XIcE1mE, +// LINUX: br i1 icmp ne (ptr @_ZTHN1XIcE1mE, +// AIX-NOT: br i1 icmp ne (ptr @_ZTHN1XIcE1mE, // LINUX_AIX: call void @_ZTHN1XIcE1mE() // LINUX_AIX: [[XEM_ADDR:%.+]] = call align 1 ptr @llvm.threadlocal.address.p0(ptr align 1 @_ZN1XIcE1mE) // LINUX_AIX: ret ptr [[XEM_ADDR]] diff --git a/clang/test/CodeGenCXX/ubsan-nullability-arg.cpp b/clang/test/CodeGenCXX/ubsan-nullability-arg.cpp index 53e324ca9eff..4cff87ca32eb 100644 --- a/clang/test/CodeGenCXX/ubsan-nullability-arg.cpp +++ b/clang/test/CodeGenCXX/ubsan-nullability-arg.cpp @@ -10,8 +10,7 @@ struct S0 { void foo1(void (S0::*_Nonnull f)()); // ITANIUM-LABEL: @_ZN10method_ptr5test1Ev(){{.*}} { -// ITANIUM: [[CMP:%.*]] = icmp ne i64 ptrtoint (ptr @_ZN10method_ptr2S04foo1Ev to i64), 0 -// ITANIUM: br i1 [[CMP]], label %[[CONT:.*]], label %[[FAIL:[^,]*]] +// ITANIUM: br i1 icmp ne (i64 ptrtoint (ptr @_ZN10method_ptr2S04foo1Ev to i64), i64 0), label %[[CONT:.*]], label %[[FAIL:[^,]*]] // ITANIUM-EMPTY: // ITANIUM-NEXT: [[FAIL]]: // ITANIUM-NEXT: call void @__ubsan_handle_nullability_arg diff --git a/clang/test/CodeGenCXX/weak-external.cpp b/clang/test/CodeGenCXX/weak-external.cpp index 02f05bfa7e1e..e30d4defd455 100644 --- a/clang/test/CodeGenCXX/weak-external.cpp +++ b/clang/test/CodeGenCXX/weak-external.cpp @@ -80,13 +80,11 @@ namespace not_weak_on_first { namespace constant_eval { [[gnu::weak]] extern int a; // CHECK-LABEL: define {{.*}} @__cxx_global_var_init - // CHECK: [[CMP:%.*]] = icmp ne ptr @_ZN13constant_eval1aE, null - // CHECK: [[ZEXT:%.*]] = zext i1 [[CMP]] to i8 + // CHECK: [[ZEXT:%.*]] = zext i1 icmp ne (ptr @_ZN13constant_eval1aE, ptr null) to i8 // CHECK: store i8 [[ZEXT]], ptr @_ZN13constant_eval6has_a1E, bool has_a1 = &a; // CHECK-LABEL: define {{.*}} @__cxx_global_var_init - // CHECK: [[CMP:%.*]] = icmp ne ptr @_ZN13constant_eval1aE, null - // CHECK: [[ZEXT:%.*]] = zext i1 [[CMP]] to i8 + // CHECK: [[ZEXT:%.*]] = zext i1 icmp ne (ptr @_ZN13constant_eval1aE, ptr null) to i8 // CHECK: store i8 [[ZEXT]], ptr @_ZN13constant_eval6has_a2E, bool has_a2 = &a != nullptr; @@ -94,16 +92,11 @@ namespace constant_eval { [[gnu::weak]] void f(); }; // CHECK-LABEL: define {{.*}} @__cxx_global_var_init - // CHECK: [[CMP:%.*]] = icmp ne i{{32|64}} ptrtoint (ptr @_ZN13constant_eval1X1fEv to i{{32|64}}), 0 - // CHECK: [[ZEXT:%.*]] = zext i1 [[CMP]] to i8 + // CHECK: [[ZEXT:%.*]] = zext i1 icmp ne (i{{32|64}} ptrtoint (ptr @_ZN13constant_eval1X1fEv to i{{32|64}}), i{{32|64}} 0) to i8 // CHECK: store i8 [[ZEXT]], ptr @_ZN13constant_eval6has_f1E, bool has_f1 = &X::f; // CHECK-LABEL: define {{.*}} @__cxx_global_var_init - // CHECK: [[CMP:%.*]] = icmp ne i{{32|64}} ptrtoint (ptr @_ZN13constant_eval1X1fEv to i{{32|64}}), 0 - // CHECK: [[CMP2:%.*]] = icmp ne i{{32|64}} ptrtoint (ptr @_ZN13constant_eval1X1fEv to i{{32|64}}), 0 - // CHECK: [[AND:%.*]] = and i1 [[CMP2]], false - // CHECK: [[OR:%.*]] = or i1 [[CMP]], [[AND]] - // CHECK: [[ZEXT:%.*]] = zext i1 [[OR]] to i8 + // CHECK: [[ZEXT:%.*]] = zext i1 icmp ne (i{{32|64}} ptrtoint (ptr @_ZN13constant_eval1X1fEv to i{{32|64}}), i{{32|64}} 0) to i8 // CHECK: store i8 [[ZEXT]], ptr @_ZN13constant_eval6has_f2E, bool has_f2 = &X::f != nullptr; } diff --git a/clang/test/Driver/linker-wrapper-image.c b/clang/test/Driver/linker-wrapper-image.c index 2bc48e6c4d88..5d5d62805e17 100644 --- a/clang/test/Driver/linker-wrapper-image.c +++ b/clang/test/Driver/linker-wrapper-image.c @@ -83,33 +83,32 @@ // CUDA: define internal void @.cuda.globals_reg(ptr %0) section ".text.startup" { // CUDA-NEXT: entry: -// CUDA-NEXT: %1 = icmp ne ptr @__start_cuda_offloading_entries, @__stop_cuda_offloading_entries -// CUDA-NEXT: br i1 %1, label %while.entry, label %while.end +// CUDA-NEXT: br i1 icmp ne (ptr @__start_cuda_offloading_entries, ptr @__stop_cuda_offloading_entries), label %while.entry, label %while.end // CUDA: while.entry: -// CUDA-NEXT: %entry1 = phi ptr [ @__start_cuda_offloading_entries, %entry ], [ %12, %if.end ] -// CUDA-NEXT: %2 = getelementptr inbounds %struct.__tgt_offload_entry, ptr %entry1, i64 0, i32 0 -// CUDA-NEXT: %addr = load ptr, ptr %2, align 8 -// CUDA-NEXT: %3 = getelementptr inbounds %struct.__tgt_offload_entry, ptr %entry1, i64 0, i32 1 -// CUDA-NEXT: %name = load ptr, ptr %3, align 8 -// CUDA-NEXT: %4 = getelementptr inbounds %struct.__tgt_offload_entry, ptr %entry1, i64 0, i32 2 -// CUDA-NEXT: %size = load i64, ptr %4, align 4 -// CUDA-NEXT: %5 = getelementptr inbounds %struct.__tgt_offload_entry, ptr %entry1, i64 0, i32 3 -// CUDA-NEXT: %flags = load i32, ptr %5, align 4 -// CUDA-NEXT: %6 = getelementptr inbounds %struct.__tgt_offload_entry, ptr %entry1, i64 0, i32 4 -// CUDA-NEXT: %textype = load i32, ptr %6, align 4 +// CUDA-NEXT: %entry1 = phi ptr [ @__start_cuda_offloading_entries, %entry ], [ %11, %if.end ] +// CUDA-NEXT: %1 = getelementptr inbounds %struct.__tgt_offload_entry, ptr %entry1, i64 0, i32 0 +// CUDA-NEXT: %addr = load ptr, ptr %1, align 8 +// CUDA-NEXT: %2 = getelementptr inbounds %struct.__tgt_offload_entry, ptr %entry1, i64 0, i32 1 +// CUDA-NEXT: %name = load ptr, ptr %2, align 8 +// CUDA-NEXT: %3 = getelementptr inbounds %struct.__tgt_offload_entry, ptr %entry1, i64 0, i32 2 +// CUDA-NEXT: %size = load i64, ptr %3, align 4 +// CUDA-NEXT: %4 = getelementptr inbounds %struct.__tgt_offload_entry, ptr %entry1, i64 0, i32 3 +// CUDA-NEXT: %flags = load i32, ptr %4, align 4 +// CUDA-NEXT: %5 = getelementptr inbounds %struct.__tgt_offload_entry, ptr %entry1, i64 0, i32 4 +// CUDA-NEXT: %textype = load i32, ptr %5, align 4 // CUDA-NEXT: %type = and i32 %flags, 7 -// CUDA-NEXT: %7 = and i32 %flags, 8 -// CUDA-NEXT: %extern = lshr i32 %7, 3 -// CUDA-NEXT: %8 = and i32 %flags, 16 -// CUDA-NEXT: %constant = lshr i32 %8, 4 -// CUDA-NEXT: %9 = and i32 %flags, 32 -// CUDA-NEXT: %normalized = lshr i32 %9, 5 -// CUDA-NEXT: %10 = icmp eq i64 %size, 0 -// CUDA-NEXT: br i1 %10, label %if.then, label %if.else +// CUDA-NEXT: %6 = and i32 %flags, 8 +// CUDA-NEXT: %extern = lshr i32 %6, 3 +// CUDA-NEXT: %7 = and i32 %flags, 16 +// CUDA-NEXT: %constant = lshr i32 %7, 4 +// CUDA-NEXT: %8 = and i32 %flags, 32 +// CUDA-NEXT: %normalized = lshr i32 %8, 5 +// CUDA-NEXT: %9 = icmp eq i64 %size, 0 +// CUDA-NEXT: br i1 %9, label %if.then, label %if.else // CUDA: if.then: -// CUDA-NEXT: %11 = call i32 @__cudaRegisterFunction(ptr %0, ptr %addr, ptr %name, ptr %name, i32 -1, ptr null, ptr null, ptr null, ptr null, ptr null) +// CUDA-NEXT: %10 = call i32 @__cudaRegisterFunction(ptr %0, ptr %addr, ptr %name, ptr %name, i32 -1, ptr null, ptr null, ptr null, ptr null, ptr null) // CUDA-NEXT: br label %if.end // CUDA: if.else: @@ -134,9 +133,9 @@ // CUDA-NEXT: br label %if.end // CUDA: if.end: -// CUDA-NEXT: %12 = getelementptr inbounds %struct.__tgt_offload_entry, ptr %entry1, i64 1 -// CUDA-NEXT: %13 = icmp eq ptr %12, @__stop_cuda_offloading_entries -// CUDA-NEXT: br i1 %13, label %while.end, label %while.entry +// CUDA-NEXT: %11 = getelementptr inbounds %struct.__tgt_offload_entry, ptr %entry1, i64 1 +// CUDA-NEXT: %12 = icmp eq ptr %11, @__stop_cuda_offloading_entries +// CUDA-NEXT: br i1 %12, label %while.end, label %while.entry // CUDA: while.end: // CUDA-NEXT: ret void @@ -183,33 +182,32 @@ // HIP: define internal void @.hip.globals_reg(ptr %0) section ".text.startup" { // HIP-NEXT: entry: -// HIP-NEXT: %1 = icmp ne ptr @__start_hip_offloading_entries, @__stop_hip_offloading_entries -// HIP-NEXT: br i1 %1, label %while.entry, label %while.end +// HIP-NEXT: br i1 icmp ne (ptr @__start_hip_offloading_entries, ptr @__stop_hip_offloading_entries), label %while.entry, label %while.end // HIP: while.entry: -// HIP-NEXT: %entry1 = phi ptr [ @__start_hip_offloading_entries, %entry ], [ %12, %if.end ] -// HIP-NEXT: %2 = getelementptr inbounds %struct.__tgt_offload_entry, ptr %entry1, i64 0, i32 0 -// HIP-NEXT: %addr = load ptr, ptr %2, align 8 -// HIP-NEXT: %3 = getelementptr inbounds %struct.__tgt_offload_entry, ptr %entry1, i64 0, i32 1 -// HIP-NEXT: %name = load ptr, ptr %3, align 8 -// HIP-NEXT: %4 = getelementptr inbounds %struct.__tgt_offload_entry, ptr %entry1, i64 0, i32 2 -// HIP-NEXT: %size = load i64, ptr %4, align 4 -// HIP-NEXT: %5 = getelementptr inbounds %struct.__tgt_offload_entry, ptr %entry1, i64 0, i32 3 -// HIP-NEXT: %flags = load i32, ptr %5, align 4 -// HIP-NEXT: %6 = getelementptr inbounds %struct.__tgt_offload_entry, ptr %entry1, i64 0, i32 4 -// HIP-NEXT: %textype = load i32, ptr %6, align 4 +// HIP-NEXT: %entry1 = phi ptr [ @__start_hip_offloading_entries, %entry ], [ %11, %if.end ] +// HIP-NEXT: %1 = getelementptr inbounds %struct.__tgt_offload_entry, ptr %entry1, i64 0, i32 0 +// HIP-NEXT: %addr = load ptr, ptr %1, align 8 +// HIP-NEXT: %2 = getelementptr inbounds %struct.__tgt_offload_entry, ptr %entry1, i64 0, i32 1 +// HIP-NEXT: %name = load ptr, ptr %2, align 8 +// HIP-NEXT: %3 = getelementptr inbounds %struct.__tgt_offload_entry, ptr %entry1, i64 0, i32 2 +// HIP-NEXT: %size = load i64, ptr %3, align 4 +// HIP-NEXT: %4 = getelementptr inbounds %struct.__tgt_offload_entry, ptr %entry1, i64 0, i32 3 +// HIP-NEXT: %flags = load i32, ptr %4, align 4 +// HIP-NEXT: %5 = getelementptr inbounds %struct.__tgt_offload_entry, ptr %entry1, i64 0, i32 4 +// HIP-NEXT: %textype = load i32, ptr %5, align 4 // HIP-NEXT: %type = and i32 %flags, 7 -// HIP-NEXT: %7 = and i32 %flags, 8 -// HIP-NEXT: %extern = lshr i32 %7, 3 -// HIP-NEXT: %8 = and i32 %flags, 16 -// HIP-NEXT: %constant = lshr i32 %8, 4 -// HIP-NEXT: %9 = and i32 %flags, 32 -// HIP-NEXT: %normalized = lshr i32 %9, 5 -// HIP-NEXT: %10 = icmp eq i64 %size, 0 -// HIP-NEXT: br i1 %10, label %if.then, label %if.else +// HIP-NEXT: %6 = and i32 %flags, 8 +// HIP-NEXT: %extern = lshr i32 %6, 3 +// HIP-NEXT: %7 = and i32 %flags, 16 +// HIP-NEXT: %constant = lshr i32 %7, 4 +// HIP-NEXT: %8 = and i32 %flags, 32 +// HIP-NEXT: %normalized = lshr i32 %8, 5 +// HIP-NEXT: %9 = icmp eq i64 %size, 0 +// HIP-NEXT: br i1 %9, label %if.then, label %if.else // HIP: if.then: -// HIP-NEXT: %11 = call i32 @__hipRegisterFunction(ptr %0, ptr %addr, ptr %name, ptr %name, i32 -1, ptr null, ptr null, ptr null, ptr null, ptr null) +// HIP-NEXT: %10 = call i32 @__hipRegisterFunction(ptr %0, ptr %addr, ptr %name, ptr %name, i32 -1, ptr null, ptr null, ptr null, ptr null, ptr null) // HIP-NEXT: br label %if.end // HIP: if.else: @@ -236,9 +234,9 @@ // HIP-NEXT: br label %if.end // HIP: if.end: -// HIP-NEXT: %12 = getelementptr inbounds %struct.__tgt_offload_entry, ptr %entry1, i64 1 -// HIP-NEXT: %13 = icmp eq ptr %12, @__stop_hip_offloading_entries -// HIP-NEXT: br i1 %13, label %while.end, label %while.entry +// HIP-NEXT: %11 = getelementptr inbounds %struct.__tgt_offload_entry, ptr %entry1, i64 1 +// HIP-NEXT: %12 = icmp eq ptr %11, @__stop_hip_offloading_entries +// HIP-NEXT: br i1 %12, label %while.end, label %while.entry // HIP: while.end: // HIP-NEXT: ret void diff --git a/clang/test/OpenMP/threadprivate_codegen.cpp b/clang/test/OpenMP/threadprivate_codegen.cpp index 5087451b944b..b27783be829d 100644 --- a/clang/test/OpenMP/threadprivate_codegen.cpp +++ b/clang/test/OpenMP/threadprivate_codegen.cpp @@ -3648,26 +3648,24 @@ int foobar() { // // CHECK-TLS1-LABEL: define {{[^@]+}}@_ZTWN6Static1sE // CHECK-TLS1-SAME: () #[[ATTR5]] comdat { -// CHECK-TLS1-NEXT: [[TMP1:%.*]] = icmp ne ptr @_ZTHN6Static1sE, null -// CHECK-TLS1-NEXT: br i1 [[TMP1]], label [[TMP2:%.*]], label [[TMP3:%.*]] -// CHECK-TLS1: 2: +// CHECK-TLS1-NEXT: br i1 icmp ne (ptr @_ZTHN6Static1sE, ptr null), label [[TMP1:%.*]], label [[TMP2:%.*]] +// CHECK-TLS1: 1: // CHECK-TLS1-NEXT: call void @_ZTHN6Static1sE() -// CHECK-TLS1-NEXT: br label [[TMP3]] -// CHECK-TLS1: 3: -// CHECK-TLS1-NEXT: [[TMP4:%.*]] = call align 4 ptr @llvm.threadlocal.address.p0(ptr align 4 @_ZN6Static1sE) -// CHECK-TLS1-NEXT: ret ptr [[TMP4]] +// CHECK-TLS1-NEXT: br label [[TMP2]] +// CHECK-TLS1: 2: +// CHECK-TLS1-NEXT: [[TMP3:%.*]] = call align 4 ptr @llvm.threadlocal.address.p0(ptr align 4 @_ZN6Static1sE) +// CHECK-TLS1-NEXT: ret ptr [[TMP3]] // // // CHECK-TLS1-LABEL: define {{[^@]+}}@_ZTW3gs3 // CHECK-TLS1-SAME: () #[[ATTR5]] comdat { -// CHECK-TLS1-NEXT: [[TMP1:%.*]] = icmp ne ptr @_ZTH3gs3, null -// CHECK-TLS1-NEXT: br i1 [[TMP1]], label [[TMP2:%.*]], label [[TMP3:%.*]] -// CHECK-TLS1: 2: +// CHECK-TLS1-NEXT: br i1 icmp ne (ptr @_ZTH3gs3, ptr null), label [[TMP1:%.*]], label [[TMP2:%.*]] +// CHECK-TLS1: 1: // CHECK-TLS1-NEXT: call void @_ZTH3gs3() -// CHECK-TLS1-NEXT: br label [[TMP3]] -// CHECK-TLS1: 3: -// CHECK-TLS1-NEXT: [[TMP4:%.*]] = call align 4 ptr @llvm.threadlocal.address.p0(ptr align 4 @gs3) -// CHECK-TLS1-NEXT: ret ptr [[TMP4]] +// CHECK-TLS1-NEXT: br label [[TMP2]] +// CHECK-TLS1: 2: +// CHECK-TLS1-NEXT: [[TMP3:%.*]] = call align 4 ptr @llvm.threadlocal.address.p0(ptr align 4 @gs3) +// CHECK-TLS1-NEXT: ret ptr [[TMP3]] // // // CHECK-TLS1-LABEL: define {{[^@]+}}@_ZTW5arr_x @@ -3952,26 +3950,24 @@ int foobar() { // // CHECK-TLS2-LABEL: define {{[^@]+}}@_ZTWN6Static1sE // CHECK-TLS2-SAME: () #[[ATTR1]] comdat { -// CHECK-TLS2-NEXT: [[TMP1:%.*]] = icmp ne ptr @_ZTHN6Static1sE, null -// CHECK-TLS2-NEXT: br i1 [[TMP1]], label [[TMP2:%.*]], label [[TMP3:%.*]] -// CHECK-TLS2: 2: +// CHECK-TLS2-NEXT: br i1 icmp ne (ptr @_ZTHN6Static1sE, ptr null), label [[TMP1:%.*]], label [[TMP2:%.*]] +// CHECK-TLS2: 1: // CHECK-TLS2-NEXT: call void @_ZTHN6Static1sE() -// CHECK-TLS2-NEXT: br label [[TMP3]] -// CHECK-TLS2: 3: -// CHECK-TLS2-NEXT: [[TMP4:%.*]] = call align 4 ptr @llvm.threadlocal.address.p0(ptr align 4 @_ZN6Static1sE) -// CHECK-TLS2-NEXT: ret ptr [[TMP4]] +// CHECK-TLS2-NEXT: br label [[TMP2]] +// CHECK-TLS2: 2: +// CHECK-TLS2-NEXT: [[TMP3:%.*]] = call align 4 ptr @llvm.threadlocal.address.p0(ptr align 4 @_ZN6Static1sE) +// CHECK-TLS2-NEXT: ret ptr [[TMP3]] // // // CHECK-TLS2-LABEL: define {{[^@]+}}@_ZTW3gs3 // CHECK-TLS2-SAME: () #[[ATTR1]] comdat { -// CHECK-TLS2-NEXT: [[TMP1:%.*]] = icmp ne ptr @_ZTH3gs3, null -// CHECK-TLS2-NEXT: br i1 [[TMP1]], label [[TMP2:%.*]], label [[TMP3:%.*]] -// CHECK-TLS2: 2: +// CHECK-TLS2-NEXT: br i1 icmp ne (ptr @_ZTH3gs3, ptr null), label [[TMP1:%.*]], label [[TMP2:%.*]] +// CHECK-TLS2: 1: // CHECK-TLS2-NEXT: call void @_ZTH3gs3() -// CHECK-TLS2-NEXT: br label [[TMP3]] -// CHECK-TLS2: 3: -// CHECK-TLS2-NEXT: [[TMP4:%.*]] = call align 4 ptr @llvm.threadlocal.address.p0(ptr align 4 @gs3) -// CHECK-TLS2-NEXT: ret ptr [[TMP4]] +// CHECK-TLS2-NEXT: br label [[TMP2]] +// CHECK-TLS2: 2: +// CHECK-TLS2-NEXT: [[TMP3:%.*]] = call align 4 ptr @llvm.threadlocal.address.p0(ptr align 4 @gs3) +// CHECK-TLS2-NEXT: ret ptr [[TMP3]] // // // CHECK-TLS2-LABEL: define {{[^@]+}}@_ZTW5arr_x @@ -4727,26 +4723,24 @@ int foobar() { // // CHECK-TLS3-LABEL: define {{[^@]+}}@_ZTWN6Static1sE // CHECK-TLS3-SAME: () #[[ATTR6]] comdat { -// CHECK-TLS3-NEXT: [[TMP1:%.*]] = icmp ne ptr @_ZTHN6Static1sE, null -// CHECK-TLS3-NEXT: br i1 [[TMP1]], label [[TMP2:%.*]], label [[TMP3:%.*]] -// CHECK-TLS3: 2: +// CHECK-TLS3-NEXT: br i1 icmp ne (ptr @_ZTHN6Static1sE, ptr null), label [[TMP1:%.*]], label [[TMP2:%.*]] +// CHECK-TLS3: 1: // CHECK-TLS3-NEXT: call void @_ZTHN6Static1sE() -// CHECK-TLS3-NEXT: br label [[TMP3]] -// CHECK-TLS3: 3: -// CHECK-TLS3-NEXT: [[TMP4:%.*]] = call align 4 ptr @llvm.threadlocal.address.p0(ptr align 4 @_ZN6Static1sE) -// CHECK-TLS3-NEXT: ret ptr [[TMP4]] +// CHECK-TLS3-NEXT: br label [[TMP2]] +// CHECK-TLS3: 2: +// CHECK-TLS3-NEXT: [[TMP3:%.*]] = call align 4 ptr @llvm.threadlocal.address.p0(ptr align 4 @_ZN6Static1sE) +// CHECK-TLS3-NEXT: ret ptr [[TMP3]] // // // CHECK-TLS3-LABEL: define {{[^@]+}}@_ZTW3gs3 // CHECK-TLS3-SAME: () #[[ATTR6]] comdat { -// CHECK-TLS3-NEXT: [[TMP1:%.*]] = icmp ne ptr @_ZTH3gs3, null -// CHECK-TLS3-NEXT: br i1 [[TMP1]], label [[TMP2:%.*]], label [[TMP3:%.*]] -// CHECK-TLS3: 2: +// CHECK-TLS3-NEXT: br i1 icmp ne (ptr @_ZTH3gs3, ptr null), label [[TMP1:%.*]], label [[TMP2:%.*]] +// CHECK-TLS3: 1: // CHECK-TLS3-NEXT: call void @_ZTH3gs3() -// CHECK-TLS3-NEXT: br label [[TMP3]] -// CHECK-TLS3: 3: -// CHECK-TLS3-NEXT: [[TMP4:%.*]] = call align 4 ptr @llvm.threadlocal.address.p0(ptr align 4 @gs3) -// CHECK-TLS3-NEXT: ret ptr [[TMP4]] +// CHECK-TLS3-NEXT: br label [[TMP2]] +// CHECK-TLS3: 2: +// CHECK-TLS3-NEXT: [[TMP3:%.*]] = call align 4 ptr @llvm.threadlocal.address.p0(ptr align 4 @gs3) +// CHECK-TLS3-NEXT: ret ptr [[TMP3]] // // // CHECK-TLS3-LABEL: define {{[^@]+}}@_ZTW5arr_x @@ -5045,26 +5039,24 @@ int foobar() { // // CHECK-TLS4-LABEL: define {{[^@]+}}@_ZTWN6Static1sE // CHECK-TLS4-SAME: () #[[ATTR2]] comdat { -// CHECK-TLS4-NEXT: [[TMP1:%.*]] = icmp ne ptr @_ZTHN6Static1sE, null -// CHECK-TLS4-NEXT: br i1 [[TMP1]], label [[TMP2:%.*]], label [[TMP3:%.*]] -// CHECK-TLS4: 2: +// CHECK-TLS4-NEXT: br i1 icmp ne (ptr @_ZTHN6Static1sE, ptr null), label [[TMP1:%.*]], label [[TMP2:%.*]] +// CHECK-TLS4: 1: // CHECK-TLS4-NEXT: call void @_ZTHN6Static1sE() -// CHECK-TLS4-NEXT: br label [[TMP3]] -// CHECK-TLS4: 3: -// CHECK-TLS4-NEXT: [[TMP4:%.*]] = call align 4 ptr @llvm.threadlocal.address.p0(ptr align 4 @_ZN6Static1sE) -// CHECK-TLS4-NEXT: ret ptr [[TMP4]] +// CHECK-TLS4-NEXT: br label [[TMP2]] +// CHECK-TLS4: 2: +// CHECK-TLS4-NEXT: [[TMP3:%.*]] = call align 4 ptr @llvm.threadlocal.address.p0(ptr align 4 @_ZN6Static1sE) +// CHECK-TLS4-NEXT: ret ptr [[TMP3]] // // // CHECK-TLS4-LABEL: define {{[^@]+}}@_ZTW3gs3 // CHECK-TLS4-SAME: () #[[ATTR2]] comdat { -// CHECK-TLS4-NEXT: [[TMP1:%.*]] = icmp ne ptr @_ZTH3gs3, null -// CHECK-TLS4-NEXT: br i1 [[TMP1]], label [[TMP2:%.*]], label [[TMP3:%.*]] -// CHECK-TLS4: 2: +// CHECK-TLS4-NEXT: br i1 icmp ne (ptr @_ZTH3gs3, ptr null), label [[TMP1:%.*]], label [[TMP2:%.*]] +// CHECK-TLS4: 1: // CHECK-TLS4-NEXT: call void @_ZTH3gs3() -// CHECK-TLS4-NEXT: br label [[TMP3]] -// CHECK-TLS4: 3: -// CHECK-TLS4-NEXT: [[TMP4:%.*]] = call align 4 ptr @llvm.threadlocal.address.p0(ptr align 4 @gs3) -// CHECK-TLS4-NEXT: ret ptr [[TMP4]] +// CHECK-TLS4-NEXT: br label [[TMP2]] +// CHECK-TLS4: 2: +// CHECK-TLS4-NEXT: [[TMP3:%.*]] = call align 4 ptr @llvm.threadlocal.address.p0(ptr align 4 @gs3) +// CHECK-TLS4-NEXT: ret ptr [[TMP3]] // // // CHECK-TLS4-LABEL: define {{[^@]+}}@_ZTW5arr_x diff --git a/llvm/include/llvm/Analysis/TargetFolder.h b/llvm/include/llvm/Analysis/TargetFolder.h index 26ec4dcef6df..f95d738a4065 100644 --- a/llvm/include/llvm/Analysis/TargetFolder.h +++ b/llvm/include/llvm/Analysis/TargetFolder.h @@ -103,7 +103,7 @@ public: auto *LC = dyn_cast(LHS); auto *RC = dyn_cast(RHS); if (LC && RC) - return ConstantFoldCompareInstOperands(P, LC, RC, DL); + return Fold(ConstantExpr::getCompare(P, LC, RC)); return nullptr; } diff --git a/llvm/include/llvm/IR/ConstantFolder.h b/llvm/include/llvm/IR/ConstantFolder.h index 65467bdbb303..ce4b44ddc855 100644 --- a/llvm/include/llvm/IR/ConstantFolder.h +++ b/llvm/include/llvm/IR/ConstantFolder.h @@ -99,7 +99,7 @@ public: auto *LC = dyn_cast(LHS); auto *RC = dyn_cast(RHS); if (LC && RC) - return ConstantFoldCompareInstruction(P, LC, RC); + return ConstantExpr::getCompare(P, LC, RC); return nullptr; } diff --git a/llvm/lib/Analysis/ConstantFolding.cpp b/llvm/lib/Analysis/ConstantFolding.cpp index c73558799556..31667ff3951f 100644 --- a/llvm/lib/Analysis/ConstantFolding.cpp +++ b/llvm/lib/Analysis/ConstantFolding.cpp @@ -1268,7 +1268,7 @@ Constant *llvm::ConstantFoldCompareInstOperands( if (!Ops1) return nullptr; - return ConstantFoldCompareInstruction(Predicate, Ops0, Ops1); + return ConstantExpr::getCompare(Predicate, Ops0, Ops1); } Constant *llvm::ConstantFoldUnaryOpOperand(unsigned Opcode, Constant *Op, diff --git a/llvm/lib/IR/ConstantFold.cpp b/llvm/lib/IR/ConstantFold.cpp index 2c99f39a0249..4622ad7e9a0e 100644 --- a/llvm/lib/IR/ConstantFold.cpp +++ b/llvm/lib/IR/ConstantFold.cpp @@ -1282,9 +1282,9 @@ Constant *llvm::ConstantFoldCompareInstruction(CmpInst::Predicate Predicate, // Fast path for splatted constants. if (Constant *C1Splat = C1->getSplatValue()) if (Constant *C2Splat = C2->getSplatValue()) - if (Constant *Elt = - ConstantFoldCompareInstruction(Predicate, C1Splat, C2Splat)) - return ConstantVector::getSplat(C1VTy->getElementCount(), Elt); + return ConstantVector::getSplat( + C1VTy->getElementCount(), + ConstantExpr::getCompare(Predicate, C1Splat, C2Splat)); // Do not iterate on scalable vector. The number of elements is unknown at // compile-time. @@ -1302,11 +1302,8 @@ Constant *llvm::ConstantFoldCompareInstruction(CmpInst::Predicate Predicate, ConstantExpr::getExtractElement(C1, ConstantInt::get(Ty, I)); Constant *C2E = ConstantExpr::getExtractElement(C2, ConstantInt::get(Ty, I)); - Constant *Elt = ConstantFoldCompareInstruction(Predicate, C1E, C2E); - if (!Elt) - return nullptr; - ResElts.push_back(Elt); + ResElts.push_back(ConstantExpr::getCompare(Predicate, C1E, C2E)); } return ConstantVector::get(ResElts); @@ -1414,7 +1411,7 @@ Constant *llvm::ConstantFoldCompareInstruction(CmpInst::Predicate Predicate, // other way if possible. // Also, if C1 is null and C2 isn't, flip them around. Predicate = ICmpInst::getSwappedPredicate(Predicate); - return ConstantFoldCompareInstruction(Predicate, C2, C1); + return ConstantExpr::getICmp(Predicate, C2, C1); } } return nullptr; diff --git a/llvm/test/Assembler/ConstantExprFold.ll b/llvm/test/Assembler/ConstantExprFold.ll index fb40f82c861b..ab7e767d767b 100644 --- a/llvm/test/Assembler/ConstantExprFold.ll +++ b/llvm/test/Assembler/ConstantExprFold.ll @@ -43,9 +43,9 @@ ; CHECK: @mul = global ptr null ; CHECK: @xor = global ptr @A ; CHECK: @B = external global %Ty -; CHECK: @icmp_ult1 = global i1 icmp ult (ptr @A, ptr getelementptr inbounds (i64, ptr @A, i64 1)) +; CHECK: @icmp_ult1 = global i1 icmp ugt (ptr getelementptr inbounds (i64, ptr @A, i64 1), ptr @A) ; CHECK: @icmp_slt = global i1 false -; CHECK: @icmp_ult2 = global i1 icmp ult (ptr @B, ptr getelementptr inbounds (%Ty, ptr @B, i64 0, i32 1)) +; CHECK: @icmp_ult2 = global i1 icmp ugt (ptr getelementptr inbounds (%Ty, ptr @B, i64 0, i32 1), ptr @B) ; CHECK: @cons = weak global i32 0, align 8 ; CHECK: @gep1 = global <2 x ptr> undef ; CHECK: @gep2 = global <2 x ptr> undef diff --git a/llvm/test/Assembler/ConstantExprNoFold.ll b/llvm/test/Assembler/ConstantExprNoFold.ll index a676a0c7eb36..4f08463d88d1 100644 --- a/llvm/test/Assembler/ConstantExprNoFold.ll +++ b/llvm/test/Assembler/ConstantExprNoFold.ll @@ -51,9 +51,9 @@ target datalayout = "p:32:32" @addrspace3 = internal addrspace(3) global i32 undef ; CHECK: @no.fold.addrspace.icmp.eq.gv.null = global i1 icmp eq (ptr addrspace(3) @addrspace3, ptr addrspace(3) null) -; CHECK: @no.fold.addrspace.icmp.eq.null.gv = global i1 icmp eq (ptr addrspace(3) null, ptr addrspace(3) @addrspace3) +; CHECK: @no.fold.addrspace.icmp.eq.null.gv = global i1 icmp eq (ptr addrspace(3) @addrspace3, ptr addrspace(3) null) ; CHECK: @no.fold.addrspace.icmp.ne.gv.null = global i1 icmp ne (ptr addrspace(3) @addrspace3, ptr addrspace(3) null) -; CHECK: @no.fold.addrspace.icmp.ne.null.gv = global i1 icmp ne (ptr addrspace(3) null, ptr addrspace(3) @addrspace3) +; CHECK: @no.fold.addrspace.icmp.ne.null.gv = global i1 icmp ne (ptr addrspace(3) @addrspace3, ptr addrspace(3) null) @no.fold.addrspace.icmp.eq.gv.null = global i1 icmp eq (ptr addrspace(3) @addrspace3, ptr addrspace(3) null) @no.fold.addrspace.icmp.eq.null.gv = global i1 icmp eq (ptr addrspace(3) null, ptr addrspace(3) @addrspace3) @no.fold.addrspace.icmp.ne.gv.null = global i1 icmp ne (ptr addrspace(3) @addrspace3, ptr addrspace(3) null) diff --git a/llvm/test/Assembler/vector-cmp.ll b/llvm/test/Assembler/vector-cmp.ll index a90046bc2426..23fe54f84595 100644 --- a/llvm/test/Assembler/vector-cmp.ll +++ b/llvm/test/Assembler/vector-cmp.ll @@ -4,7 +4,7 @@ target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:128:128" target triple = "i686-apple-darwin9.2.2" -; CHECK: @1 = global <4 x i1> icmp slt (<4 x i32> , <4 x i32> ) +; CHECK: @1 = global <4 x i1> define <4 x i1> @foo(<4 x float> %a, <4 x float> %b) nounwind { entry: diff --git a/llvm/test/CodeGen/AMDGPU/lower-ctor-dtor-constexpr-alias.ll b/llvm/test/CodeGen/AMDGPU/lower-ctor-dtor-constexpr-alias.ll index 2ad40ef5e547..95fc47469b51 100644 --- a/llvm/test/CodeGen/AMDGPU/lower-ctor-dtor-constexpr-alias.ll +++ b/llvm/test/CodeGen/AMDGPU/lower-ctor-dtor-constexpr-alias.ll @@ -48,8 +48,7 @@ define void @bar() addrspace(1) { ; CHECK-LABEL: define weak_odr amdgpu_kernel void @amdgcn.device.init( ; CHECK-SAME: ) #[[ATTR1:[0-9]+]] { ; CHECK-NEXT: entry: -; CHECK-NEXT: [[TMP0:%.*]] = icmp ne ptr addrspace(1) @__init_array_start, @__init_array_end -; CHECK-NEXT: br i1 [[TMP0]], label [[WHILE_ENTRY:%.*]], label [[WHILE_END:%.*]] +; CHECK-NEXT: br i1 icmp ne (ptr addrspace(1) @__init_array_start, ptr addrspace(1) @__init_array_end), label [[WHILE_ENTRY:%.*]], label [[WHILE_END:%.*]] ; CHECK: while.entry: ; CHECK-NEXT: [[PTR:%.*]] = phi ptr addrspace(1) [ @__init_array_start, [[ENTRY:%.*]] ], [ [[NEXT:%.*]], [[WHILE_ENTRY]] ] ; CHECK-NEXT: [[CALLBACK:%.*]] = load ptr, ptr addrspace(1) [[PTR]], align 8 diff --git a/llvm/test/CodeGen/AMDGPU/lower-ctor-dtor.ll b/llvm/test/CodeGen/AMDGPU/lower-ctor-dtor.ll index 503f3b1d896f..c4f0821caacd 100644 --- a/llvm/test/CodeGen/AMDGPU/lower-ctor-dtor.ll +++ b/llvm/test/CodeGen/AMDGPU/lower-ctor-dtor.ll @@ -63,8 +63,7 @@ define internal void @bar() { ; CHECK-LABEL: define weak_odr amdgpu_kernel void @amdgcn.device.init( ; CHECK-SAME: ) #[[ATTR0:[0-9]+]] { ; CHECK-NEXT: entry: -; CHECK-NEXT: [[TMP0:%.*]] = icmp ne ptr addrspace(1) @__init_array_start, @__init_array_end -; CHECK-NEXT: br i1 [[TMP0]], label [[WHILE_ENTRY:%.*]], label [[WHILE_END:%.*]] +; CHECK-NEXT: br i1 icmp ne (ptr addrspace(1) @__init_array_start, ptr addrspace(1) @__init_array_end), label [[WHILE_ENTRY:%.*]], label [[WHILE_END:%.*]] ; CHECK: while.entry: ; CHECK-NEXT: [[PTR:%.*]] = phi ptr addrspace(1) [ @__init_array_start, [[ENTRY:%.*]] ], [ [[NEXT:%.*]], [[WHILE_ENTRY]] ] ; CHECK-NEXT: [[CALLBACK:%.*]] = load ptr, ptr addrspace(1) [[PTR]], align 8 diff --git a/llvm/test/CodeGen/AMDGPU/lower-multiple-ctor-dtor.ll b/llvm/test/CodeGen/AMDGPU/lower-multiple-ctor-dtor.ll index 9d00b676d661..f2d73b24c35d 100644 --- a/llvm/test/CodeGen/AMDGPU/lower-multiple-ctor-dtor.ll +++ b/llvm/test/CodeGen/AMDGPU/lower-multiple-ctor-dtor.ll @@ -55,8 +55,7 @@ define internal void @bar.5() { ; CHECK-LABEL: define weak_odr amdgpu_kernel void @amdgcn.device.init( ; CHECK-SAME: ) #[[ATTR0:[0-9]+]] { ; CHECK-NEXT: entry: -; CHECK-NEXT: [[TMP0:%.*]] = icmp ne ptr addrspace(1) @__init_array_start, @__init_array_end -; CHECK-NEXT: br i1 [[TMP0]], label [[WHILE_ENTRY:%.*]], label [[WHILE_END:%.*]] +; CHECK-NEXT: br i1 icmp ne (ptr addrspace(1) @__init_array_start, ptr addrspace(1) @__init_array_end), label [[WHILE_ENTRY:%.*]], label [[WHILE_END:%.*]] ; CHECK: while.entry: ; CHECK-NEXT: [[PTR:%.*]] = phi ptr addrspace(1) [ @__init_array_start, [[ENTRY:%.*]] ], [ [[NEXT:%.*]], [[WHILE_ENTRY]] ] ; CHECK-NEXT: [[CALLBACK:%.*]] = load ptr, ptr addrspace(1) [[PTR]], align 8 diff --git a/llvm/test/Instrumentation/MemorySanitizer/check-constant-shadow.ll b/llvm/test/Instrumentation/MemorySanitizer/check-constant-shadow.ll index df032b385054..2e89bbd2dcff 100644 --- a/llvm/test/Instrumentation/MemorySanitizer/check-constant-shadow.ll +++ b/llvm/test/Instrumentation/MemorySanitizer/check-constant-shadow.ll @@ -73,8 +73,7 @@ entry: } ; CHECK-LABEL: @MaybeUninitializedRetNoUndef -; CONST: [[CMP:%.*]] = icmp ne i32 extractelement (<4 x i32> bitcast (<2 x i64> to <4 x i32>), i64 0), 0 -; CONST: br i1 [[CMP]] +; CONST: br i1 icmp ne (i32 extractelement (<4 x i32> bitcast (<2 x i64> to <4 x i32>), i64 0), i32 0) ; CONST: call void @__msan_warning_with_origin_noreturn ; CHECK: call void @__msan_init() diff --git a/llvm/test/Instrumentation/SanitizerBinaryMetadata/atomics.ll b/llvm/test/Instrumentation/SanitizerBinaryMetadata/atomics.ll index 82b65fe33cd6..7d4086c49503 100644 --- a/llvm/test/Instrumentation/SanitizerBinaryMetadata/atomics.ll +++ b/llvm/test/Instrumentation/SanitizerBinaryMetadata/atomics.ll @@ -2037,8 +2037,7 @@ entry: ; CHECK-LABEL: __sanitizer_metadata_atomics.module_ctor ; CHECK-DAG: entry: -; CHECK-NEXT: [[CMP:%.*]] = icmp ne ptr @__sanitizer_metadata_atomics_add, null -; CHECK-NEXT: br i1 [[CMP]], label %callfunc, label %ret +; CHECK-NEXT: br i1 icmp ne (ptr @__sanitizer_metadata_atomics_add, ptr null), label %callfunc, label %ret ; CHECK-DAG: callfunc: ; CHECK-NEXT: call void @__sanitizer_metadata_atomics_add(i32 2, ptr @__start_sanmd_atomics, ptr @__stop_sanmd_atomics) ; CHECK-NEXT: br label %ret @@ -2047,8 +2046,7 @@ entry: ; CHECK-LABEL: __sanitizer_metadata_atomics.module_dtor ; CHECK-DAG: entry: -; CHECK-NEXT: [[CMP:%.*]] = icmp ne ptr @__sanitizer_metadata_atomics_del, null -; CHECK-NEXT: br i1 [[CMP]], label %callfunc, label %ret +; CHECK-NEXT: br i1 icmp ne (ptr @__sanitizer_metadata_atomics_del, ptr null), label %callfunc, label %ret ; CHECK-DAG: callfunc: ; CHECK-NEXT: call void @__sanitizer_metadata_atomics_del(i32 2, ptr @__start_sanmd_atomics, ptr @__stop_sanmd_atomics) ; CHECK-NEXT: br label %ret @@ -2057,8 +2055,7 @@ entry: ; CHECK-LABEL: __sanitizer_metadata_covered.module_ctor ; CHECK-DAG: entry: -; CHECK-NEXT: [[CMP:%.*]] = icmp ne ptr @__sanitizer_metadata_covered_add, null -; CHECK-NEXT: br i1 [[CMP]], label %callfunc, label %ret +; CHECK-NEXT: br i1 icmp ne (ptr @__sanitizer_metadata_covered_add, ptr null), label %callfunc, label %ret ; CHECK-DAG: callfunc: ; CHECK-NEXT: call void @__sanitizer_metadata_covered_add(i32 2, ptr @__start_sanmd_covered, ptr @__stop_sanmd_covered) ; CHECK-NEXT: br label %ret @@ -2067,8 +2064,7 @@ entry: ; CHECK-LABEL: __sanitizer_metadata_covered.module_dtor ; CHECK-DAG: entry: -; CHECK-NEXT: [[CMP:%.*]] = icmp ne ptr @__sanitizer_metadata_covered_del, null -; CHECK-NEXT: br i1 [[CMP]], label %callfunc, label %ret +; CHECK-NEXT: br i1 icmp ne (ptr @__sanitizer_metadata_covered_del, ptr null), label %callfunc, label %ret ; CHECK-DAG: callfunc: ; CHECK-NEXT: call void @__sanitizer_metadata_covered_del(i32 2, ptr @__start_sanmd_covered, ptr @__stop_sanmd_covered) ; CHECK-NEXT: br label %ret diff --git a/llvm/test/Transforms/Attributor/value-simplify.ll b/llvm/test/Transforms/Attributor/value-simplify.ll index 53edd566c542..62d4f63677df 100644 --- a/llvm/test/Transforms/Attributor/value-simplify.ll +++ b/llvm/test/Transforms/Attributor/value-simplify.ll @@ -1396,6 +1396,11 @@ define internal void @not_called2() { ret void } define internal void @not_called3() { +; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) +; TUNIT-LABEL: define {{[^@]+}}@not_called3 +; TUNIT-SAME: () #[[ATTR2]] { +; TUNIT-NEXT: ret void +; ; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) ; CGSCC-LABEL: define {{[^@]+}}@not_called3 ; CGSCC-SAME: () #[[ATTR1]] { @@ -1417,7 +1422,7 @@ define i1 @user_of_not_called() { ; CHECK-LABEL: define {{[^@]+}}@user_of_not_called() { ; CHECK-NEXT: call void @useFnDecl(ptr addrspace(42) noundef nonnull addrspacecast (ptr @not_called1 to ptr addrspace(42))) ; CHECK-NEXT: call void @useFnDef(ptr addrspace(42) noundef nonnull addrspacecast (ptr @not_called2 to ptr addrspace(42))) -; CHECK-NEXT: ret i1 false +; CHECK-NEXT: ret i1 icmp eq (ptr addrspace(42) addrspacecast (ptr @not_called3 to ptr addrspace(42)), ptr addrspace(42) null) ; call void @useFnDecl(ptr addrspace(42) addrspacecast (ptr @not_called1 to ptr addrspace(42))) call void @useFnDef(ptr addrspace(42) addrspacecast (ptr @not_called2 to ptr addrspace(42))) diff --git a/llvm/test/Transforms/InstCombine/binop-select-cast-of-select-cond.ll b/llvm/test/Transforms/InstCombine/binop-select-cast-of-select-cond.ll index 7dc2fe1cb88e..b0da6d80d05a 100644 --- a/llvm/test/Transforms/InstCombine/binop-select-cast-of-select-cond.ll +++ b/llvm/test/Transforms/InstCombine/binop-select-cast-of-select-cond.ll @@ -232,7 +232,7 @@ define i64 @pr64669(i64 %a) { ; CHECK-LABEL: define i64 @pr64669 ; CHECK-SAME: (i64 [[A:%.*]]) { ; CHECK-NEXT: [[TMP1:%.*]] = add i64 [[A]], 1 -; CHECK-NEXT: [[ADD:%.*]] = select i1 icmp ne (ptr getelementptr inbounds ([72 x i32], ptr @b, i64 0, i64 25), ptr @c), i64 [[TMP1]], i64 0 +; CHECK-NEXT: [[ADD:%.*]] = select i1 icmp ne (ptr getelementptr inbounds (i8, ptr @b, i64 100), ptr @c), i64 [[TMP1]], i64 0 ; CHECK-NEXT: ret i64 [[ADD]] ; %mul = select i1 icmp ne (ptr getelementptr inbounds ([72 x i32], ptr @b, i64 0, i64 25), ptr @c), i64 %a, i64 0 diff --git a/llvm/test/Transforms/InstCombine/constant-fold-address-space-pointer.ll b/llvm/test/Transforms/InstCombine/constant-fold-address-space-pointer.ll index dafe3900fef3..857704f58028 100644 --- a/llvm/test/Transforms/InstCombine/constant-fold-address-space-pointer.ll +++ b/llvm/test/Transforms/InstCombine/constant-fold-address-space-pointer.ll @@ -132,8 +132,7 @@ define i1 @constant_fold_inttoptr_null(i16 %i) { define i1 @constant_fold_ptrtoint_null() { ; CHECK-LABEL: @constant_fold_ptrtoint_null( -; CHECK-NEXT: [[X:%.*]] = icmp eq i16 ptrtoint (ptr addrspace(3) @g to i16), 0 -; CHECK-NEXT: ret i1 [[X]] +; CHECK-NEXT: ret i1 icmp eq (ptr addrspace(3) @g, ptr addrspace(3) null) ; %x = icmp eq i16 ptrtoint (ptr addrspace(3) @g to i16), ptrtoint (ptr addrspace(3) null to i16) ret i1 %x @@ -141,8 +140,7 @@ define i1 @constant_fold_ptrtoint_null() { define i1 @constant_fold_ptrtoint_null_2() { ; CHECK-LABEL: @constant_fold_ptrtoint_null_2( -; CHECK-NEXT: [[X:%.*]] = icmp eq i16 0, ptrtoint (ptr addrspace(3) @g to i16) -; CHECK-NEXT: ret i1 [[X]] +; CHECK-NEXT: ret i1 icmp eq (ptr addrspace(3) @g, ptr addrspace(3) null) ; %x = icmp eq i16 ptrtoint (ptr addrspace(3) null to i16), ptrtoint (ptr addrspace(3) @g to i16) ret i1 %x diff --git a/llvm/test/Transforms/InstCombine/getelementptr.ll b/llvm/test/Transforms/InstCombine/getelementptr.ll index e29f1a7cf006..e82c168ced01 100644 --- a/llvm/test/Transforms/InstCombine/getelementptr.ll +++ b/llvm/test/Transforms/InstCombine/getelementptr.ll @@ -537,8 +537,7 @@ define i32 @test21() { define i1 @test22() { ; CHECK-LABEL: @test22( -; CHECK-NEXT: [[C:%.*]] = icmp ult ptr getelementptr inbounds (i8, ptr @A, i64 4), getelementptr (i8, ptr @B, i64 8) -; CHECK-NEXT: ret i1 [[C]] +; CHECK-NEXT: ret i1 icmp ult (ptr getelementptr inbounds (i8, ptr @A, i64 4), ptr getelementptr (i8, ptr @B, i64 8)) ; %C = icmp ult ptr getelementptr (i32, ptr @A, i64 1), getelementptr (i32, ptr @B, i64 2) diff --git a/llvm/test/Transforms/InstCombine/hoist-xor-by-constant-from-xor-by-value.ll b/llvm/test/Transforms/InstCombine/hoist-xor-by-constant-from-xor-by-value.ll index 200e7ba8e677..d75dbcf9c9b9 100644 --- a/llvm/test/Transforms/InstCombine/hoist-xor-by-constant-from-xor-by-value.ll +++ b/llvm/test/Transforms/InstCombine/hoist-xor-by-constant-from-xor-by-value.ll @@ -94,8 +94,7 @@ entry: define i16 @constantexpr2() { ; CHECK-LABEL: @constantexpr2( -; CHECK-NEXT: [[I0:%.*]] = icmp ne ptr getelementptr inbounds (i8, ptr @global_constant3, i64 40), @global_constant4 -; CHECK-NEXT: [[I1:%.*]] = zext i1 [[I0]] to i16 +; CHECK-NEXT: [[I1:%.*]] = zext i1 icmp ne (ptr getelementptr inbounds (i8, ptr @global_constant3, i64 40), ptr @global_constant4) to i16 ; CHECK-NEXT: [[I2:%.*]] = load ptr, ptr @global_constant5, align 1 ; CHECK-NEXT: [[I3:%.*]] = load i16, ptr [[I2]], align 1 ; CHECK-NEXT: [[I4:%.*]] = xor i16 [[I3]], [[I1]] diff --git a/llvm/test/Transforms/InstCombine/pr33453.ll b/llvm/test/Transforms/InstCombine/pr33453.ll index 45f87b753006..23a232dd0b9a 100644 --- a/llvm/test/Transforms/InstCombine/pr33453.ll +++ b/llvm/test/Transforms/InstCombine/pr33453.ll @@ -6,7 +6,7 @@ define float @patatino() { ; CHECK-LABEL: @patatino( -; CHECK-NEXT: [[FMUL:%.*]] = uitofp i1 mul (i1 icmp eq (ptr getelementptr inbounds (i16, ptr @g2, i64 1), ptr @g1), i1 icmp eq (ptr getelementptr inbounds (i16, ptr @g2, i64 1), ptr @g1)) to float +; CHECK-NEXT: [[FMUL:%.*]] = uitofp i1 mul (i1 icmp eq (ptr getelementptr inbounds (i8, ptr @g2, i64 2), ptr @g1), i1 icmp eq (ptr getelementptr inbounds (i8, ptr @g2, i64 2), ptr @g1)) to float ; CHECK-NEXT: ret float [[FMUL]] ; %uitofp1 = uitofp i1 icmp eq (ptr getelementptr inbounds (i16, ptr @g2, i64 1), ptr @g1) to float diff --git a/llvm/test/Transforms/InstCombine/pr83947.ll b/llvm/test/Transforms/InstCombine/pr83947.ll index c1d601ff6371..63a242abc925 100644 --- a/llvm/test/Transforms/InstCombine/pr83947.ll +++ b/llvm/test/Transforms/InstCombine/pr83947.ll @@ -6,7 +6,7 @@ define void @masked_scatter1() { ; CHECK-LABEL: define void @masked_scatter1() { -; CHECK-NEXT: call void @llvm.masked.scatter.nxv4i32.nxv4p0( zeroinitializer, shufflevector ( insertelement ( poison, ptr @c, i64 0), poison, zeroinitializer), i32 4, shufflevector ( insertelement ( poison, i1 icmp eq (ptr getelementptr inbounds (i32, ptr @b, i64 1), ptr @c), i64 0), poison, zeroinitializer)) +; CHECK-NEXT: call void @llvm.masked.scatter.nxv4i32.nxv4p0( zeroinitializer, shufflevector ( insertelement ( poison, ptr @c, i64 0), poison, zeroinitializer), i32 4, shufflevector ( insertelement ( poison, i1 icmp eq (ptr getelementptr inbounds (i8, ptr @b, i64 4), ptr @c), i64 0), poison, zeroinitializer)) ; CHECK-NEXT: ret void ; call void @llvm.masked.scatter.nxv4i32.nxv4p0( zeroinitializer, splat (ptr @c), i32 4, splat (i1 icmp eq (ptr getelementptr (i32, ptr @b, i64 1), ptr @c))) @@ -59,7 +59,7 @@ define void @masked_scatter6() { define void @masked_scatter7() { ; CHECK-LABEL: define void @masked_scatter7() { -; CHECK-NEXT: call void @llvm.masked.scatter.v2i32.v2p0(<2 x i32> zeroinitializer, <2 x ptr> , i32 4, <2 x i1> ) +; CHECK-NEXT: call void @llvm.masked.scatter.v2i32.v2p0(<2 x i32> zeroinitializer, <2 x ptr> , i32 4, <2 x i1> ) ; CHECK-NEXT: ret void ; call void @llvm.masked.scatter.v2i32.v2p0(<2 x i32> zeroinitializer, <2 x ptr> splat (ptr @c), i32 4, <2 x i1> splat (i1 icmp eq (ptr getelementptr (i32, ptr @b, i64 1), ptr @c))) diff --git a/llvm/test/Transforms/InstCombine/rem.ll b/llvm/test/Transforms/InstCombine/rem.ll index ae390e72a4b7..a8fa72c37d32 100644 --- a/llvm/test/Transforms/InstCombine/rem.ll +++ b/llvm/test/Transforms/InstCombine/rem.ll @@ -522,7 +522,7 @@ define i32 @pr27968_0(i1 %c0, ptr %p) { ; CHECK-NEXT: [[V:%.*]] = load volatile i32, ptr [[P:%.*]], align 4 ; CHECK-NEXT: br label [[IF_END]] ; CHECK: if.end: -; CHECK-NEXT: br i1 icmp eq (ptr getelementptr inbounds ([5 x i16], ptr @a, i64 0, i64 4), ptr @b), label [[REM_IS_SAFE:%.*]], label [[REM_IS_UNSAFE:%.*]] +; CHECK-NEXT: br i1 icmp eq (ptr getelementptr inbounds (i8, ptr @a, i64 8), ptr @b), label [[REM_IS_SAFE:%.*]], label [[REM_IS_UNSAFE:%.*]] ; CHECK: rem.is.safe: ; CHECK-NEXT: ret i32 0 ; CHECK: rem.is.unsafe: @@ -591,7 +591,7 @@ define i32 @pr27968_2(i1 %c0, ptr %p) { ; CHECK-NEXT: [[V:%.*]] = load volatile i32, ptr [[P:%.*]], align 4 ; CHECK-NEXT: br label [[IF_END]] ; CHECK: if.end: -; CHECK-NEXT: br i1 icmp eq (ptr getelementptr inbounds ([5 x i16], ptr @a, i64 0, i64 4), ptr @b), label [[REM_IS_SAFE:%.*]], label [[REM_IS_UNSAFE:%.*]] +; CHECK-NEXT: br i1 icmp eq (ptr getelementptr inbounds (i8, ptr @a, i64 8), ptr @b), label [[REM_IS_SAFE:%.*]], label [[REM_IS_UNSAFE:%.*]] ; CHECK: rem.is.safe: ; CHECK-NEXT: ret i32 0 ; CHECK: rem.is.unsafe: diff --git a/llvm/test/Transforms/InstCombine/select-and-or.ll b/llvm/test/Transforms/InstCombine/select-and-or.ll index 0f7acd4d56c0..0965e1c8348e 100644 --- a/llvm/test/Transforms/InstCombine/select-and-or.ll +++ b/llvm/test/Transforms/InstCombine/select-and-or.ll @@ -431,7 +431,7 @@ define i1 @not_false_not_use3(i1 %x, i1 %y) { define i1 @demorgan_select_infloop1(i1 %L) { ; CHECK-LABEL: @demorgan_select_infloop1( ; CHECK-NEXT: [[NOT_L:%.*]] = xor i1 [[L:%.*]], true -; CHECK-NEXT: [[C15:%.*]] = select i1 [[NOT_L]], i1 xor (i1 icmp eq (ptr getelementptr inbounds (i16, ptr @g2, i64 1), ptr @g1), i1 icmp eq (ptr getelementptr inbounds (i16, ptr @g2, i64 1), ptr @g1)), i1 false +; CHECK-NEXT: [[C15:%.*]] = select i1 [[NOT_L]], i1 xor (i1 icmp eq (ptr getelementptr inbounds (i8, ptr @g2, i64 2), ptr @g1), i1 icmp eq (ptr getelementptr inbounds (i8, ptr @g2, i64 2), ptr @g1)), i1 false ; CHECK-NEXT: ret i1 [[C15]] ; %not.L = xor i1 %L, true @@ -443,7 +443,7 @@ define i1 @demorgan_select_infloop1(i1 %L) { define i1 @demorgan_select_infloop2(i1 %L) { ; CHECK-LABEL: @demorgan_select_infloop2( ; CHECK-NEXT: [[NOT_L:%.*]] = xor i1 [[L:%.*]], true -; CHECK-NEXT: [[C15:%.*]] = select i1 [[NOT_L]], i1 true, i1 xor (i1 icmp eq (ptr getelementptr inbounds (i16, ptr @g2, i64 1), ptr @g1), i1 icmp eq (ptr getelementptr inbounds (i16, ptr @g2, i64 1), ptr @g1)) +; CHECK-NEXT: [[C15:%.*]] = select i1 [[NOT_L]], i1 true, i1 xor (i1 icmp eq (ptr getelementptr inbounds (i8, ptr @g2, i64 2), ptr @g1), i1 icmp eq (ptr getelementptr inbounds (i8, ptr @g2, i64 2), ptr @g1)) ; CHECK-NEXT: ret i1 [[C15]] ; %not.L = xor i1 %L, true diff --git a/llvm/test/Transforms/InstCombine/select-safe-transforms.ll b/llvm/test/Transforms/InstCombine/select-safe-transforms.ll index 1a4848934c9f..f0072e24161d 100644 --- a/llvm/test/Transforms/InstCombine/select-safe-transforms.ll +++ b/llvm/test/Transforms/InstCombine/select-safe-transforms.ll @@ -85,7 +85,7 @@ define <2 x i1> @xor_and2(<2 x i1> %c, <2 x i32> %X, <2 x i32> %Y) { define <2 x i1> @xor_and3(<2 x i1> %c, <2 x i32> %X, <2 x i32> %Y) { ; CHECK-LABEL: @xor_and3( ; CHECK-NEXT: [[COMP:%.*]] = icmp uge <2 x i32> [[X:%.*]], [[Y:%.*]] -; CHECK-NEXT: [[SEL:%.*]] = select <2 x i1> [[C:%.*]], <2 x i1> [[COMP]], <2 x i1> +; CHECK-NEXT: [[SEL:%.*]] = select <2 x i1> [[C:%.*]], <2 x i1> [[COMP]], <2 x i1> ; CHECK-NEXT: ret <2 x i1> [[SEL]] ; %comp = icmp ult <2 x i32> %X, %Y @@ -122,7 +122,7 @@ define <2 x i1> @xor_or2(<2 x i1> %c, <2 x i32> %X, <2 x i32> %Y) { define <2 x i1> @xor_or3(<2 x i1> %c, <2 x i32> %X, <2 x i32> %Y) { ; CHECK-LABEL: @xor_or3( ; CHECK-NEXT: [[COMP:%.*]] = icmp uge <2 x i32> [[X:%.*]], [[Y:%.*]] -; CHECK-NEXT: [[SEL:%.*]] = select <2 x i1> [[C:%.*]], <2 x i1> , <2 x i1> [[COMP]] +; CHECK-NEXT: [[SEL:%.*]] = select <2 x i1> [[C:%.*]], <2 x i1> , <2 x i1> [[COMP]] ; CHECK-NEXT: ret <2 x i1> [[SEL]] ; %comp = icmp ult <2 x i32> %X, %Y diff --git a/llvm/test/Transforms/InstSimplify/ConstProp/bitcast.ll b/llvm/test/Transforms/InstSimplify/ConstProp/bitcast.ll index 9c75b66db50c..99b1eb6ef07d 100644 --- a/llvm/test/Transforms/InstSimplify/ConstProp/bitcast.ll +++ b/llvm/test/Transforms/InstSimplify/ConstProp/bitcast.ll @@ -35,8 +35,7 @@ define i1 @bad_icmp_constexpr_bitcast() { define i1 @bad_fcmp_constexpr_bitcast() { ; CHECK-LABEL: @bad_fcmp_constexpr_bitcast( -; CHECK-NEXT: [[CMP:%.*]] = fcmp oeq float bitcast (i32 ptrtoint (ptr @c to i32) to float), bitcast (i32 add (i32 ptrtoint (ptr @d to i32), i32 2) to float) -; CHECK-NEXT: ret i1 [[CMP]] +; CHECK-NEXT: ret i1 fcmp oeq (float bitcast (i32 ptrtoint (ptr @c to i32) to float), float bitcast (i32 add (i32 ptrtoint (ptr @d to i32), i32 2) to float)) ; %cmp = fcmp oeq float bitcast (i32 ptrtoint (ptr @c to i32) to float), bitcast (i32 add (i32 ptrtoint (ptr @d to i32), i32 2) to float) ret i1 %cmp @@ -46,8 +45,7 @@ define i1 @bad_fcmp_constexpr_bitcast() { define i1 @fcmp_constexpr_oeq(float %conv) { ; CHECK-LABEL: @fcmp_constexpr_oeq( -; CHECK-NEXT: [[CMP:%.*]] = fcmp oeq float bitcast (i32 ptrtoint (ptr @a to i32) to float), bitcast (i32 ptrtoint (ptr @a to i32) to float) -; CHECK-NEXT: ret i1 [[CMP]] +; CHECK-NEXT: ret i1 fcmp oeq (float bitcast (i32 ptrtoint (ptr @a to i32) to float), float bitcast (i32 ptrtoint (ptr @a to i32) to float)) ; %cmp = fcmp oeq float bitcast (i32 ptrtoint (ptr @a to i32) to float), bitcast (i32 ptrtoint (ptr @a to i32) to float) ret i1 %cmp @@ -57,8 +55,7 @@ define i1 @fcmp_constexpr_oeq(float %conv) { define i1 @fcmp_constexpr_une(float %conv) { ; CHECK-LABEL: @fcmp_constexpr_une( -; CHECK-NEXT: [[CMP:%.*]] = fcmp une float bitcast (i32 ptrtoint (ptr @a to i32) to float), bitcast (i32 ptrtoint (ptr @a to i32) to float) -; CHECK-NEXT: ret i1 [[CMP]] +; CHECK-NEXT: ret i1 fcmp une (float bitcast (i32 ptrtoint (ptr @a to i32) to float), float bitcast (i32 ptrtoint (ptr @a to i32) to float)) ; %cmp = fcmp une float bitcast (i32 ptrtoint (ptr @a to i32) to float), bitcast (i32 ptrtoint (ptr @a to i32) to float) ret i1 %cmp diff --git a/llvm/test/Transforms/InstSimplify/ConstProp/icmp-global.ll b/llvm/test/Transforms/InstSimplify/ConstProp/icmp-global.ll index 3ef9552eb79d..1d7ed23d3e82 100644 --- a/llvm/test/Transforms/InstSimplify/ConstProp/icmp-global.ll +++ b/llvm/test/Transforms/InstSimplify/ConstProp/icmp-global.ll @@ -47,8 +47,7 @@ define i1 @ule_constexpr_null(ptr %x) { define i1 @slt_constexpr_null(ptr %x) { ; CHECK-LABEL: @slt_constexpr_null( -; CHECK-NEXT: [[CMP:%.*]] = icmp slt ptr @ugt_null_constexpr, null -; CHECK-NEXT: ret i1 [[CMP]] +; CHECK-NEXT: ret i1 icmp slt (ptr @ugt_null_constexpr, ptr null) ; %cmp = icmp slt ptr @ugt_null_constexpr, null ret i1 %cmp @@ -58,8 +57,7 @@ define i1 @slt_constexpr_null(ptr %x) { define i1 @ult_constexpr_constexpr_one(ptr %x) { ; CHECK-LABEL: @ult_constexpr_constexpr_one( -; CHECK-NEXT: [[CMP:%.*]] = icmp ult ptr @ugt_null_constexpr, inttoptr (i32 1 to ptr) -; CHECK-NEXT: ret i1 [[CMP]] +; CHECK-NEXT: ret i1 icmp ugt (ptr inttoptr (i32 1 to ptr), ptr @ugt_null_constexpr) ; %cmp = icmp ult ptr @ugt_null_constexpr, inttoptr (i32 1 to ptr) ret i1 %cmp @@ -88,8 +86,7 @@ define i1 @global_ugt_null() { define i1 @global_sgt_null() { ; CHECK-LABEL: @global_sgt_null( -; CHECK-NEXT: [[CMP:%.*]] = icmp sgt ptr @g, null -; CHECK-NEXT: ret i1 [[CMP]] +; CHECK-NEXT: ret i1 icmp sgt (ptr @g, ptr null) ; %cmp = icmp sgt ptr @g, null ret i1 %cmp @@ -98,8 +95,7 @@ define i1 @global_sgt_null() { ; Should not fold to true, as the gep computes a null value. define i1 @global_out_of_bounds_gep_ne_null() { ; CHECK-LABEL: @global_out_of_bounds_gep_ne_null( -; CHECK-NEXT: [[CMP:%.*]] = icmp ne ptr getelementptr (i8, ptr @g3, i64 sub (i64 0, i64 ptrtoint (ptr @g3 to i64))), null -; CHECK-NEXT: ret i1 [[CMP]] +; CHECK-NEXT: ret i1 icmp ne (ptr getelementptr (i8, ptr @g3, i64 sub (i64 0, i64 ptrtoint (ptr @g3 to i64))), ptr null) ; %cmp = icmp ne ptr getelementptr (i8, ptr @g3, i64 sub (i64 0, i64 ptrtoint (ptr @g3 to i64))), null ret i1 %cmp @@ -125,8 +121,7 @@ define i1 @global_gep_ugt_null() { define i1 @global_gep_sgt_null() { ; CHECK-LABEL: @global_gep_sgt_null( -; CHECK-NEXT: [[CMP:%.*]] = icmp sgt ptr getelementptr inbounds (i8, ptr @g, i64 8), null -; CHECK-NEXT: ret i1 [[CMP]] +; CHECK-NEXT: ret i1 icmp sgt (ptr getelementptr inbounds (i8, ptr @g, i64 8), ptr null) ; %gep = getelementptr inbounds [2 x i32], ptr @g, i64 1 %cmp = icmp sgt ptr %gep, null @@ -137,8 +132,7 @@ define i1 @global_gep_sgt_null() { ; are equal. define i1 @null_gep_ne_null() { ; CHECK-LABEL: @null_gep_ne_null( -; CHECK-NEXT: [[CMP:%.*]] = icmp ne ptr getelementptr (i8, ptr null, i64 ptrtoint (ptr @g2_weak to i64)), null -; CHECK-NEXT: ret i1 [[CMP]] +; CHECK-NEXT: ret i1 icmp ne (ptr getelementptr (i8, ptr null, i64 ptrtoint (ptr @g2_weak to i64)), ptr null) ; %gep = getelementptr i8, ptr null, i64 ptrtoint (ptr @g2_weak to i64) %cmp = icmp ne ptr %gep, null @@ -147,8 +141,7 @@ define i1 @null_gep_ne_null() { define i1 @null_gep_ugt_null() { ; CHECK-LABEL: @null_gep_ugt_null( -; CHECK-NEXT: [[CMP:%.*]] = icmp ugt ptr getelementptr (i8, ptr null, i64 ptrtoint (ptr @g2_weak to i64)), null -; CHECK-NEXT: ret i1 [[CMP]] +; CHECK-NEXT: ret i1 icmp ugt (ptr getelementptr (i8, ptr null, i64 ptrtoint (ptr @g2_weak to i64)), ptr null) ; %gep = getelementptr i8, ptr null, i64 ptrtoint (ptr @g2_weak to i64) %cmp = icmp ugt ptr %gep, null @@ -157,8 +150,7 @@ define i1 @null_gep_ugt_null() { define i1 @null_gep_sgt_null() { ; CHECK-LABEL: @null_gep_sgt_null( -; CHECK-NEXT: [[CMP:%.*]] = icmp sgt ptr getelementptr (i8, ptr null, i64 ptrtoint (ptr @g2_weak to i64)), null -; CHECK-NEXT: ret i1 [[CMP]] +; CHECK-NEXT: ret i1 icmp sgt (ptr getelementptr (i8, ptr null, i64 ptrtoint (ptr @g2_weak to i64)), ptr null) ; %gep = getelementptr i8, ptr null, i64 ptrtoint (ptr @g2_weak to i64) %cmp = icmp sgt ptr %gep, null @@ -185,8 +177,7 @@ define i1 @null_gep_ugt_null_constant_int() { define i1 @null_gep_ne_global() { ; CHECK-LABEL: @null_gep_ne_global( -; CHECK-NEXT: [[CMP:%.*]] = icmp ne ptr getelementptr (i8, ptr null, i64 ptrtoint (ptr @g3 to i64)), @g3 -; CHECK-NEXT: ret i1 [[CMP]] +; CHECK-NEXT: ret i1 icmp ne (ptr getelementptr (i8, ptr null, i64 ptrtoint (ptr @g3 to i64)), ptr @g3) ; %gep = getelementptr i8, ptr null, i64 ptrtoint (ptr @g3 to i64) %cmp = icmp ne ptr %gep, @g3 @@ -195,8 +186,7 @@ define i1 @null_gep_ne_global() { define i1 @null_gep_ult_global() { ; CHECK-LABEL: @null_gep_ult_global( -; CHECK-NEXT: [[CMP:%.*]] = icmp ult ptr getelementptr (i8, ptr null, i64 ptrtoint (ptr @g3 to i64)), @g3 -; CHECK-NEXT: ret i1 [[CMP]] +; CHECK-NEXT: ret i1 icmp ult (ptr getelementptr (i8, ptr null, i64 ptrtoint (ptr @g3 to i64)), ptr @g3) ; %gep = getelementptr i8, ptr null, i64 ptrtoint (ptr @g3 to i64) %cmp = icmp ult ptr %gep, @g3 @@ -205,8 +195,7 @@ define i1 @null_gep_ult_global() { define i1 @null_gep_slt_global() { ; CHECK-LABEL: @null_gep_slt_global( -; CHECK-NEXT: [[CMP:%.*]] = icmp slt ptr getelementptr ([2 x i32], ptr null, i64 ptrtoint (ptr @g2 to i64)), @g -; CHECK-NEXT: ret i1 [[CMP]] +; CHECK-NEXT: ret i1 icmp slt (ptr getelementptr ([2 x i32], ptr null, i64 ptrtoint (ptr @g2 to i64)), ptr @g) ; %gep = getelementptr [2 x i32], ptr null, i64 ptrtoint (ptr @g2 to i64) %cmp = icmp slt ptr %gep, @g @@ -233,8 +222,7 @@ define i1 @global_gep_ugt_global() { define i1 @global_gep_sgt_global() { ; CHECK-LABEL: @global_gep_sgt_global( -; CHECK-NEXT: [[CMP:%.*]] = icmp sgt ptr getelementptr inbounds (i8, ptr @g, i64 8), @g -; CHECK-NEXT: ret i1 [[CMP]] +; CHECK-NEXT: ret i1 icmp sgt (ptr getelementptr inbounds (i8, ptr @g, i64 8), ptr @g) ; %gep = getelementptr inbounds [2 x i32], ptr @g, i64 1 %cmp = icmp sgt ptr %gep, @g @@ -244,8 +232,7 @@ define i1 @global_gep_sgt_global() { ; This should not fold to true, as the offset is negative. define i1 @global_gep_ugt_global_neg_offset() { ; CHECK-LABEL: @global_gep_ugt_global_neg_offset( -; CHECK-NEXT: [[CMP:%.*]] = icmp ugt ptr getelementptr (i8, ptr @g, i64 -8), @g -; CHECK-NEXT: ret i1 [[CMP]] +; CHECK-NEXT: ret i1 icmp ugt (ptr getelementptr (i8, ptr @g, i64 -8), ptr @g) ; %gep = getelementptr [2 x i32], ptr @g, i64 -1 %cmp = icmp ugt ptr %gep, @g @@ -254,8 +241,7 @@ define i1 @global_gep_ugt_global_neg_offset() { define i1 @global_gep_sgt_global_neg_offset() { ; CHECK-LABEL: @global_gep_sgt_global_neg_offset( -; CHECK-NEXT: [[CMP:%.*]] = icmp sgt ptr getelementptr (i8, ptr @g, i64 -8), @g -; CHECK-NEXT: ret i1 [[CMP]] +; CHECK-NEXT: ret i1 icmp sgt (ptr getelementptr (i8, ptr @g, i64 -8), ptr @g) ; %gep = getelementptr [2 x i32], ptr @g, i64 -1 %cmp = icmp sgt ptr %gep, @g @@ -274,8 +260,7 @@ define i1 @global_gep_ugt_global_gep() { ; Should not fold due to signed comparison. define i1 @global_gep_sgt_global_gep() { ; CHECK-LABEL: @global_gep_sgt_global_gep( -; CHECK-NEXT: [[CMP:%.*]] = icmp sgt ptr getelementptr inbounds (i8, ptr @g, i64 4), @g -; CHECK-NEXT: ret i1 [[CMP]] +; CHECK-NEXT: ret i1 icmp sgt (ptr getelementptr inbounds (i8, ptr @g, i64 4), ptr @g) ; %gep2 = getelementptr inbounds [2 x i32], ptr @g, i64 0, i64 1 %cmp = icmp sgt ptr %gep2, @g @@ -295,8 +280,7 @@ declare void @func() define i1 @global_no_cfi() { ; CHECK-LABEL: @global_no_cfi( -; CHECK-NEXT: [[CMP:%.*]] = icmp eq ptr @func, no_cfi @func -; CHECK-NEXT: ret i1 [[CMP]] +; CHECK-NEXT: ret i1 icmp eq (ptr @func, ptr no_cfi @func) ; %cmp = icmp eq ptr @func, no_cfi @func ret i1 %cmp @@ -306,8 +290,7 @@ define i1 @blockaddr_no_cfi() { ; CHECK-LABEL: @blockaddr_no_cfi( ; CHECK-NEXT: br label [[BB:%.*]] ; CHECK: bb: -; CHECK-NEXT: [[CMP:%.*]] = icmp eq ptr blockaddress(@blockaddr_no_cfi, [[BB]]), no_cfi @func -; CHECK-NEXT: ret i1 [[CMP]] +; CHECK-NEXT: ret i1 icmp eq (ptr blockaddress(@blockaddr_no_cfi, [[BB]]), ptr no_cfi @func) ; br label %bb @@ -318,8 +301,7 @@ bb: define i1 @global_no_cfi_dso_local_equivalent() { ; CHECK-LABEL: @global_no_cfi_dso_local_equivalent( -; CHECK-NEXT: [[CMP:%.*]] = icmp eq ptr dso_local_equivalent @func, no_cfi @func -; CHECK-NEXT: ret i1 [[CMP]] +; CHECK-NEXT: ret i1 icmp eq (ptr dso_local_equivalent @func, ptr no_cfi @func) ; %cmp = icmp eq ptr dso_local_equivalent @func, no_cfi @func ret i1 %cmp diff --git a/llvm/test/Transforms/InstSimplify/bitcast-vector-fold.ll b/llvm/test/Transforms/InstSimplify/bitcast-vector-fold.ll index 68ff0859beb2..b9e2753d3feb 100644 --- a/llvm/test/Transforms/InstSimplify/bitcast-vector-fold.ll +++ b/llvm/test/Transforms/InstSimplify/bitcast-vector-fold.ll @@ -76,8 +76,7 @@ define <4 x i32> @test9(<1 x i64> %y) { define <1 x i1> @test10() { ; CHECK-LABEL: @test10( -; CHECK-NEXT: [[RET:%.*]] = icmp eq <1 x i64> to i64)>, zeroinitializer -; CHECK-NEXT: ret <1 x i1> [[RET]] +; CHECK-NEXT: ret <1 x i1> to i64), i64 0)> ; %ret = icmp eq <1 x i64> to i64)>, zeroinitializer ret <1 x i1> %ret diff --git a/llvm/test/Transforms/InstSimplify/compare.ll b/llvm/test/Transforms/InstSimplify/compare.ll index 1e78bb232f79..0f72cd813f2f 100644 --- a/llvm/test/Transforms/InstSimplify/compare.ll +++ b/llvm/test/Transforms/InstSimplify/compare.ll @@ -3078,8 +3078,7 @@ define i1 @globals_inequal() { ; TODO: Never equal define i1 @globals_offset_inequal() { ; CHECK-LABEL: @globals_offset_inequal( -; CHECK-NEXT: [[RES:%.*]] = icmp ne ptr getelementptr inbounds (i8, ptr @A, i32 1), getelementptr inbounds (i8, ptr @B, i32 1) -; CHECK-NEXT: ret i1 [[RES]] +; CHECK-NEXT: ret i1 icmp ne (ptr getelementptr inbounds (i8, ptr @A, i32 1), ptr getelementptr inbounds (i8, ptr @B, i32 1)) ; %a.off = getelementptr i8, ptr @A, i32 1 %b.off = getelementptr i8, ptr @B, i32 1 @@ -3101,8 +3100,7 @@ define i1 @test_byval_global_inequal(ptr byval(i32) %a) { define i1 @neg_global_alias() { ; CHECK-LABEL: @neg_global_alias( -; CHECK-NEXT: [[RES:%.*]] = icmp ne ptr @A, @A.alias -; CHECK-NEXT: ret i1 [[RES]] +; CHECK-NEXT: ret i1 icmp ne (ptr @A, ptr @A.alias) ; %res = icmp ne ptr @A, @A.alias ret i1 %res diff --git a/llvm/test/Transforms/InstSimplify/past-the-end.ll b/llvm/test/Transforms/InstSimplify/past-the-end.ll index cc2fe6f36fcd..1e146d18327a 100644 --- a/llvm/test/Transforms/InstSimplify/past-the-end.ll +++ b/llvm/test/Transforms/InstSimplify/past-the-end.ll @@ -21,8 +21,7 @@ define zeroext i1 @no_offsets() { define zeroext i1 @both_past_the_end() { ; CHECK-LABEL: @both_past_the_end( -; CHECK-NEXT: [[T:%.*]] = icmp eq ptr getelementptr inbounds (i8, ptr @opte_a, i32 4), getelementptr inbounds (i8, ptr @opte_b, i32 4) -; CHECK-NEXT: ret i1 [[T]] +; CHECK-NEXT: ret i1 icmp eq (ptr getelementptr inbounds (i8, ptr @opte_a, i32 4), ptr getelementptr inbounds (i8, ptr @opte_b, i32 4)) ; %x = getelementptr i32, ptr @opte_a, i32 1 %y = getelementptr i32, ptr @opte_b, i32 1 @@ -36,8 +35,7 @@ define zeroext i1 @both_past_the_end() { define zeroext i1 @just_one_past_the_end() { ; CHECK-LABEL: @just_one_past_the_end( -; CHECK-NEXT: [[T:%.*]] = icmp eq ptr getelementptr inbounds (i8, ptr @opte_a, i32 4), @opte_b -; CHECK-NEXT: ret i1 [[T]] +; CHECK-NEXT: ret i1 icmp eq (ptr getelementptr inbounds (i8, ptr @opte_a, i32 4), ptr @opte_b) ; %x = getelementptr i32, ptr @opte_a, i32 1 %t = icmp eq ptr %x, @opte_b diff --git a/llvm/test/Transforms/JumpThreading/constant-fold-status.ll b/llvm/test/Transforms/JumpThreading/constant-fold-status.ll index 3d98b0d6eecc..ae984df1caa3 100644 --- a/llvm/test/Transforms/JumpThreading/constant-fold-status.ll +++ b/llvm/test/Transforms/JumpThreading/constant-fold-status.ll @@ -8,8 +8,7 @@ ; status check that is hidden under EXPENSIVE_CHECKS. ; CHECK-LABEL: entry: -; CHECK-NEXT: %.not = icmp eq i32 ptrtoint (ptr @a to i32), 0 -; CHECK-NEXT: br i1 %.not, label %overflow, label %cont +; CHECK-NEXT: br i1 icmp eq (i32 ptrtoint (ptr @a to i32), i32 0), label %overflow, label %cont @a = internal global i16 0 diff --git a/llvm/test/Transforms/LowerTypeTests/cfi-direct-call1.ll b/llvm/test/Transforms/LowerTypeTests/cfi-direct-call1.ll index 3afb4875ca28..1b7039f905cc 100644 --- a/llvm/test/Transforms/LowerTypeTests/cfi-direct-call1.ll +++ b/llvm/test/Transforms/LowerTypeTests/cfi-direct-call1.ll @@ -56,9 +56,8 @@ entry: ; FULL: %fptr1 = select i1 %cmp.i, ptr @local_func1, ptr @local_func2 ; Indirect references to extern_weak and extern_decl must go through jump table -; FULL: [[CMP:%.*]] = icmp ne ptr @extern_weak, null -; FULL: [[SEL:%.*]] = select i1 [[CMP]], ptr getelementptr inbounds ([4 x [8 x i8]], ptr @.cfi.jumptable, i64 0, i64 2), ptr null -; FULL: %fptr2 = select i1 %cmp.i, ptr [[SEL]], ptr getelementptr inbounds ([4 x [8 x i8]], ptr @.cfi.jumptable, i64 0, i64 3) +; FULL: %0 = select i1 icmp ne (ptr @extern_weak, ptr null), ptr getelementptr inbounds ([4 x [8 x i8]], ptr @.cfi.jumptable, i64 0, i64 2), ptr null +; FULL: %fptr2 = select i1 %cmp.i, ptr %0, ptr getelementptr inbounds ([4 x [8 x i8]], ptr @.cfi.jumptable, i64 0, i64 3) ; Direct calls to extern_weak and extern_decl should go to original names ; FULL: %call5 = tail call i32 @extern_decl() @@ -84,9 +83,8 @@ entry: ; THIN: %fptr1 = select i1 %cmp.i, ptr @local_func1, ptr @local_func2 ; Indirect references to extern_weak and extern_decl must go through jump table -; THIN: [[CMP:%.*]] = icmp ne ptr @extern_weak, null -; THIN: [[SEL:%.*]] = select i1 [[CMP]], ptr @extern_weak.cfi_jt, ptr null -; THIN: %fptr2 = select i1 %cmp.i, ptr [[SEL]], ptr @extern_decl.cfi_jt +; THIN: %0 = select i1 icmp ne (ptr @extern_weak, ptr null), ptr @extern_weak.cfi_jt, ptr null +; THIN: %fptr2 = select i1 %cmp.i, ptr %0, ptr @extern_decl.cfi_jt ; Direct calls to extern_weak and extern_decl should go to original names ; THIN: %call5 = tail call i32 @extern_decl() diff --git a/llvm/test/Transforms/LowerTypeTests/function-weak.ll b/llvm/test/Transforms/LowerTypeTests/function-weak.ll index 33876bda356c..5f9041cd21b3 100644 --- a/llvm/test/Transforms/LowerTypeTests/function-weak.ll +++ b/llvm/test/Transforms/LowerTypeTests/function-weak.ll @@ -34,10 +34,9 @@ declare !type !0 extern_weak void @f() ; CHECK: define zeroext i1 @check_f() define zeroext i1 @check_f() { entry: -; CHECK: [[CMP:%.*]] = icmp ne ptr @f, null -; CHECK: [[SEL:%.*]] = select i1 [[CMP]], ptr @[[JT:.*]], ptr null -; CHECK: [[CMP2:%.*]] = icmp ne ptr [[SEL]], null -; CHECK: ret i1 [[CMP2]] +; CHECK: %0 = select i1 icmp ne (ptr @f, ptr null), ptr @[[JT:.*]], ptr null +; CHECK: %1 = icmp ne ptr %0, null +; ret i1 %1 ret i1 icmp ne (ptr @f, ptr null) } @@ -51,12 +50,11 @@ entry: define void @struct() { ; CHECK-LABEL: define void @struct() { -; CHECK: [[CMP:%.*]] = icmp ne ptr @f, null -; CHECK: [[SEL:%.*]] = select i1 [[CMP]], ptr @.cfi.jumptable, ptr null -; CHECK-NEXT: [[CMP2:%.*]] = icmp ne ptr [[SEL]], null -; CHECK-NEXT: [[IV:%.*]] = insertvalue { i1, i8 } poison, i1 [[CMP2]], 0 -; CHECK-NEXT: [[IV2:%.*]] = insertvalue { i1, i8 } [[IV]], i8 0, 1 -; CHECK-NEXT: %x = extractvalue { i1, i8 } [[IV2]], 0 +; CHECK: %0 = select i1 icmp ne (ptr @f, ptr null), ptr @.cfi.jumptable, ptr null +; CHECK-NEXT: %1 = icmp ne ptr %0, null +; CHECK-NEXT: %2 = insertvalue { i1, i8 } poison, i1 %1, 0 +; CHECK-NEXT: %3 = insertvalue { i1, i8 } %2, i8 0, 1 +; CHECK-NEXT: %x = extractvalue { i1, i8 } %3, 0 entry: %x = extractvalue { i1, i8 } { i1 icmp ne (ptr @f, ptr null), i8 0 }, 0 @@ -66,16 +64,14 @@ entry: define void @phi(i1 %c) { ; CHECK-LABEL: define void @phi(i1 %c) { ; CHECK: entry: -; CHECK: [[CMP:%.*]] = icmp ne ptr @f, null -; CHECK: [[SEL:%.*]] = select i1 [[CMP]], ptr @.cfi.jumptable, ptr null +; CHECK: %0 = select i1 icmp ne (ptr @f, ptr null), ptr @.cfi.jumptable, ptr null ; CHECK: br i1 %c, label %if, label %join ; CHECK: if: -; CHECK: [[CMP2:%.*]] = icmp ne ptr @f, null -; CHECK: [[SEL2:%.*]] = select i1 [[CMP2]], ptr @.cfi.jumptable, ptr null +; CHECK: %1 = select i1 icmp ne (ptr @f, ptr null), ptr @.cfi.jumptable, ptr null ; CHECK: br label %join ; CHECK: join: -; CHECK: %phi = phi ptr [ [[SEL2]], %if ], [ null, %entry ] -; CHECK: %phi2 = phi ptr [ null, %if ], [ [[SEL]], %entry ] +; CHECK: %phi = phi ptr [ %1, %if ], [ null, %entry ] +; CHECK: %phi2 = phi ptr [ null, %if ], [ %0, %entry ] entry: br i1 %c, label %if, label %join @@ -94,19 +90,17 @@ define void @phi2(i1 %c, i32 %x) { ; CHECK: entry: ; CHECK: br i1 %c, label %if, label %else ; CHECK: if: ; preds = %entry -; CHECK: [[CMP:%.*]] = icmp ne ptr @f, null -; CHECK: [[SEL:%.*]] = select i1 [[CMP]], ptr @.cfi.jumptable, ptr null +; CHECK: %0 = select i1 icmp ne (ptr @f, ptr null), ptr @.cfi.jumptable, ptr null ; CHECK: switch i32 %x, label %join [ ; CHECK: i32 0, label %join ; CHECK: ] ; CHECK: else: ; preds = %entry -; CHECK: [[CMP2:%.*]] = icmp ne ptr @f, null -; CHECK: [[SEL2:%.*]] = select i1 [[CMP2]], ptr @.cfi.jumptable, ptr null +; CHECK: %1 = select i1 icmp ne (ptr @f, ptr null), ptr @.cfi.jumptable, ptr null ; CHECK: switch i32 %x, label %join [ ; CHECK: i32 0, label %join ; CHECK: ] ; CHECK: join: ; preds = %else, %else, %if, %if -; CHECK: %phi2 = phi ptr [ [[SEL]], %if ], [ [[SEL]], %if ], [ [[SEL2]], %else ], [ [[SEL2]], %else ] +; CHECK: %phi2 = phi ptr [ %0, %if ], [ %0, %if ], [ %1, %else ], [ %1, %else ] entry: br i1 %c, label %if, label %else @@ -138,29 +132,23 @@ define i1 @foo(ptr %p) { ; RISCV: define private void @[[JT]]() #{{.*}} align 8 { ; LOONGARCH64: define private void @[[JT]]() #{{.*}} align 8 { -; CHECK-LABEL: define internal void @__cfi_global_var_init() section ".text.startup" { +; CHECK: define internal void @__cfi_global_var_init() section ".text.startup" { ; CHECK-NEXT: entry: -; CHECK-NEXT: [[CMP:%.*]] = icmp ne ptr @f, null -; CHECK-NEXT: [[SEL:%.*]] = select i1 [[CMP]], ptr @[[JT]], ptr null -; CHECK-NEXT: store ptr [[SEL]], ptr @x, align 8 -; CHECK-NEXT: [[CMP2:%.*]] = icmp ne ptr @f, null -; CHECK-NEXT: [[SEL2:%.*]] = select i1 [[CMP2]], ptr @[[JT]], ptr null -; CHECK-NEXT: store ptr [[SEL2]], ptr @x2, align 8 -; CHECK-NEXT: [[CMP3:%.*]] = icmp ne ptr @f, null -; CHECK-NEXT: [[SEL3:%.*]] = select i1 [[CMP3]], ptr @[[JT]], ptr null -; CHECK-NEXT: store ptr [[SEL3]], ptr @x3, align 8 -; CHECK-NEXT: [[CMP4:%.*]] = icmp ne ptr @f, null -; CHECK-NEXT: [[SEL4:%.*]] = select i1 [[CMP4]], ptr @[[JT]], ptr null -; CHECK-NEXT: [[GEP:%.*]] = getelementptr i8, ptr [[SEL4]], i64 42 -; CHECK-NEXT: store ptr [[GEP]], ptr @x4, align 8 -; CHECK-NEXT: [[CMP5:%.*]] = icmp ne ptr @f, null -; CHECK-NEXT: [[SEL5:%.*]] = select i1 [[CMP5]], ptr @[[JT]], ptr null -; CHECK-NEXT: [[IV:%.*]] = insertvalue { ptr, ptr, i32 } poison, ptr [[SEL5]], 0 -; CHECK-NEXT: [[CMP6:%.*]] = icmp ne ptr @f, null -; CHECK-NEXT: [[SEL6:%.*]] = select i1 [[CMP6]], ptr @[[JT]], ptr null -; CHECK-NEXT: [[IV2:%.*]] = insertvalue { ptr, ptr, i32 } [[IV]], ptr [[SEL6]], 1 -; CHECK-NEXT: [[IV3:%.*]] = insertvalue { ptr, ptr, i32 } [[IV2]], i32 42, 2 -; CHECK-NEXT: store { ptr, ptr, i32 } [[IV3]], ptr @s, align 8 +; CHECK-NEXT: %0 = select i1 icmp ne (ptr @f, ptr null), ptr @[[JT]], ptr null +; CHECK-NEXT: store ptr %0, ptr @x, align 8 +; CHECK-NEXT: %1 = select i1 icmp ne (ptr @f, ptr null), ptr @[[JT]], ptr null +; CHECK-NEXT: store ptr %1, ptr @x2, align 8 +; CHECK-NEXT: %2 = select i1 icmp ne (ptr @f, ptr null), ptr @[[JT]], ptr null +; CHECK-NEXT: store ptr %2, ptr @x3, align 8 +; CHECK-NEXT: %3 = select i1 icmp ne (ptr @f, ptr null), ptr @[[JT]], ptr null +; CHECK-NEXT: %4 = getelementptr i8, ptr %3, i64 42 +; CHECK-NEXT: store ptr %4, ptr @x4, align 8 +; CHECK-NEXT: %5 = select i1 icmp ne (ptr @f, ptr null), ptr @[[JT]], ptr null +; CHECK-NEXT: %6 = insertvalue { ptr, ptr, i32 } poison, ptr %5, 0 +; CHECK-NEXT: %7 = select i1 icmp ne (ptr @f, ptr null), ptr @[[JT]], ptr null +; CHECK-NEXT: %8 = insertvalue { ptr, ptr, i32 } %6, ptr %7, 1 +; CHECK-NEXT: %9 = insertvalue { ptr, ptr, i32 } %8, i32 42, 2 +; CHECK-NEXT: store { ptr, ptr, i32 } %9, ptr @s, align 8 ; CHECK-NEXT: ret void ; CHECK-NEXT: } diff --git a/llvm/test/Transforms/SCCP/conditions-ranges.ll b/llvm/test/Transforms/SCCP/conditions-ranges.ll index bb3764160f72..25719d2bee52 100644 --- a/llvm/test/Transforms/SCCP/conditions-ranges.ll +++ b/llvm/test/Transforms/SCCP/conditions-ranges.ll @@ -631,13 +631,10 @@ false: define void @f14_constexpr2() { ; CHECK-LABEL: @f14_constexpr2( ; CHECK-NEXT: entry: -; CHECK-NEXT: [[BC_1:%.*]] = icmp eq i32 ptrtoint (ptr @A to i32), ptrtoint (ptr @B to i32) -; CHECK-NEXT: br i1 [[BC_1]], label [[TRUE:%.*]], label [[FALSE:%.*]] +; CHECK-NEXT: br i1 icmp eq (i32 ptrtoint (ptr @A to i32), i32 ptrtoint (ptr @B to i32)), label [[TRUE:%.*]], label [[FALSE:%.*]] ; CHECK: true: -; CHECK-NEXT: [[F_1:%.*]] = icmp ne i32 ptrtoint (ptr @B to i32), ptrtoint (ptr @A to i32) -; CHECK-NEXT: call void @use(i1 [[F_1]]) -; CHECK-NEXT: [[F_2:%.*]] = icmp eq i32 ptrtoint (ptr @B to i32), ptrtoint (ptr @A to i32) -; CHECK-NEXT: call void @use(i1 [[F_2]]) +; CHECK-NEXT: call void @use(i1 icmp ne (i32 ptrtoint (ptr @B to i32), i32 ptrtoint (ptr @A to i32))) +; CHECK-NEXT: call void @use(i1 icmp eq (i32 ptrtoint (ptr @B to i32), i32 ptrtoint (ptr @A to i32))) ; CHECK-NEXT: ret void ; CHECK: false: ; CHECK-NEXT: ret void diff --git a/llvm/test/Transforms/SimplifyCFG/phi-to-select-constexpr-icmp.ll b/llvm/test/Transforms/SimplifyCFG/phi-to-select-constexpr-icmp.ll index a56e7041bf2e..307de76bc321 100644 --- a/llvm/test/Transforms/SimplifyCFG/phi-to-select-constexpr-icmp.ll +++ b/llvm/test/Transforms/SimplifyCFG/phi-to-select-constexpr-icmp.ll @@ -8,7 +8,7 @@ define i1 @test(i1 %c) { ; CHECK-LABEL: @test( ; CHECK-NEXT: entry: -; CHECK-NEXT: [[SPEC_SELECT:%.*]] = select i1 [[C:%.*]], i1 false, i1 icmp ult (ptr @glob, ptr inttoptr (i64 -40 to ptr)) +; CHECK-NEXT: [[SPEC_SELECT:%.*]] = select i1 [[C:%.*]], i1 false, i1 icmp ugt (ptr inttoptr (i64 -40 to ptr), ptr @glob) ; CHECK-NEXT: ret i1 [[SPEC_SELECT]] ; entry: -- GitLab From 0a62a99aa610a7a8cf739208603646bc01b37347 Mon Sep 17 00:00:00 2001 From: David Green Date: Wed, 22 May 2024 19:28:24 +0100 Subject: [PATCH 176/452] [SelectOpt] Add handling for not conditions. (#92517) This patch attempts to help the SelectOpt pass detect select groups made up of conditions and not(conditions). Usually these are canonicalized in instcombine to remove the not and invert the true/false values, but this will not happen for Loginal operations, which can be beneficial to convert if they are part of a larger select group. The handling for not's are mostly handled in the SelectLike, which can be marked as Inverted in order to reverse the TrueValue and FalseValue. This helps fix a regression in fortran minloc constructs, after #84628 helped simplify a loop with branches into a loop with selects. --- llvm/lib/CodeGen/SelectOptimize.cpp | 82 ++++-- llvm/test/CodeGen/AArch64/selectopt-not.ll | 326 ++++++++++++++------- 2 files changed, 284 insertions(+), 124 deletions(-) diff --git a/llvm/lib/CodeGen/SelectOptimize.cpp b/llvm/lib/CodeGen/SelectOptimize.cpp index 2e03ae6aec94..0a5f0a861d48 100644 --- a/llvm/lib/CodeGen/SelectOptimize.cpp +++ b/llvm/lib/CodeGen/SelectOptimize.cpp @@ -130,7 +130,11 @@ public: class SelectLike { SelectLike(Instruction *I) : I(I) {} + /// The select (/or) instruction. Instruction *I; + /// Whether this select is inverted, "not(cond), FalseVal, TrueVal", as + /// opposed to the original condition. + bool Inverted = false; public: /// Match a select or select-like instruction, returning a SelectLike. @@ -153,14 +157,22 @@ public: bool isValid() { return I; } operator bool() { return isValid(); } + /// Invert the select by inverting the condition and switching the operands. + void setInverted() { + assert(!Inverted && "Trying to invert an inverted SelectLike"); + assert(isa(getCondition()) && + cast(getCondition())->getOpcode() == + Instruction::Xor); + Inverted = true; + } + bool isInverted() const { return Inverted; } + Instruction *getI() { return I; } const Instruction *getI() const { return I; } Type *getType() const { return I->getType(); } - /// Return the condition for the SelectLike instruction. For example the - /// condition of a select or c in `or(zext(c), x)` - Value *getCondition() const { + Value *getNonInvertedCondition() const { if (auto *Sel = dyn_cast(I)) return Sel->getCondition(); // Or(zext) case @@ -177,11 +189,24 @@ public: llvm_unreachable("Unhandled case in getCondition"); } + /// Return the condition for the SelectLike instruction. For example the + /// condition of a select or c in `or(zext(c), x)` + Value *getCondition() const { + Value *CC = getNonInvertedCondition(); + // For inverted conditions the CC is checked when created to be a not + // (xor) instruction. + if (Inverted) + return cast(CC)->getOperand(0); + return CC; + } + /// Return the true value for the SelectLike instruction. Note this may not /// exist for all SelectLike instructions. For example, for `or(zext(c), x)` /// the true value would be `or(x,1)`. As this value does not exist, nullptr /// is returned. - Value *getTrueValue() const { + Value *getTrueValue(bool HonorInverts = true) const { + if (Inverted && HonorInverts) + return getFalseValue(/*HonorInverts=*/false); if (auto *Sel = dyn_cast(I)) return Sel->getTrueValue(); // Or(zext) case - The true value is Or(X), so return nullptr as the value @@ -195,7 +220,9 @@ public: /// Return the false value for the SelectLike instruction. For example the /// getFalseValue of a select or `x` in `or(zext(c), x)` (which is /// `select(c, x|1, x)`) - Value *getFalseValue() const { + Value *getFalseValue(bool HonorInverts = true) const { + if (Inverted && HonorInverts) + return getTrueValue(/*HonorInverts=*/false); if (auto *Sel = dyn_cast(I)) return Sel->getFalseValue(); // Or(zext) case - return the operand which is not the zext. @@ -216,8 +243,8 @@ public: /// InstCostMap. This may need to be generated for select-like instructions. Scaled64 getTrueOpCost(DenseMap &InstCostMap, const TargetTransformInfo *TTI) { - if (auto *Sel = dyn_cast(I)) - if (auto *I = dyn_cast(Sel->getTrueValue())) + if (isa(I)) + if (auto *I = dyn_cast(getTrueValue())) return InstCostMap.contains(I) ? InstCostMap[I].NonPredCost : Scaled64::getZero(); @@ -242,8 +269,8 @@ public: Scaled64 getFalseOpCost(DenseMap &InstCostMap, const TargetTransformInfo *TTI) { - if (auto *Sel = dyn_cast(I)) - if (auto *I = dyn_cast(Sel->getFalseValue())) + if (isa(I)) + if (auto *I = dyn_cast(getFalseValue())) return InstCostMap.contains(I) ? InstCostMap[I].NonPredCost : Scaled64::getZero(); @@ -510,9 +537,10 @@ getTrueOrFalseValue(SelectOptimizeImpl::SelectLike SI, bool isTrue, for (SelectInst *DefSI = dyn_cast(SI.getI()); DefSI != nullptr && Selects.count(DefSI); DefSI = dyn_cast(V)) { - assert(DefSI->getCondition() == SI.getCondition() && - "The condition of DefSI does not match with SI"); - V = (isTrue ? DefSI->getTrueValue() : DefSI->getFalseValue()); + if (DefSI->getCondition() == SI.getCondition()) + V = (isTrue ? DefSI->getTrueValue() : DefSI->getFalseValue()); + else // Handle inverted SI + V = (!isTrue ? DefSI->getTrueValue() : DefSI->getFalseValue()); } if (isa(SI.getI())) { @@ -632,18 +660,19 @@ void SelectOptimizeImpl::convertProfitableSIGroups(SelectGroups &ProfSIGroups) { // Delete the unconditional branch that was just created by the split. StartBlock->getTerminator()->eraseFromParent(); - // Move any debug/pseudo instructions that were in-between the select - // group to the newly-created end block. - SmallVector DebugPseudoINS; + // Move any debug/pseudo instructions and not's that were in-between the + // select group to the newly-created end block. + SmallVector SinkInstrs; auto DIt = SI.getI()->getIterator(); while (&*DIt != LastSI.getI()) { if (DIt->isDebugOrPseudoInst()) - DebugPseudoINS.push_back(&*DIt); + SinkInstrs.push_back(&*DIt); + if (match(&*DIt, m_Not(m_Specific(SI.getCondition())))) + SinkInstrs.push_back(&*DIt); DIt++; } - for (auto *DI : DebugPseudoINS) { + for (auto *DI : SinkInstrs) DI->moveBeforePreserving(&*EndBlock->getFirstInsertionPt()); - } // Duplicate implementation for DbgRecords, the non-instruction debug-info // format. Helper lambda for moving DbgRecords to the end block. @@ -765,6 +794,13 @@ void SelectOptimizeImpl::collectSelectGroups(BasicBlock &BB, ++BBIt; continue; } + + // Skip not(select(..)), if the not is part of the same select group + if (match(NI, m_Not(m_Specific(SI.getCondition())))) { + ++BBIt; + continue; + } + // We only allow selects in the same group, not other select-like // instructions. if (!isa(NI)) @@ -773,6 +809,10 @@ void SelectOptimizeImpl::collectSelectGroups(BasicBlock &BB, SelectLike NSI = SelectLike::match(NI); if (NSI && SI.getCondition() == NSI.getCondition()) { SIGroup.push_back(NSI); + } else if (NSI && match(NSI.getCondition(), + m_Not(m_Specific(SI.getCondition())))) { + NSI.setInverted(); + SIGroup.push_back(NSI); } else break; ++BBIt; @@ -783,6 +823,12 @@ void SelectOptimizeImpl::collectSelectGroups(BasicBlock &BB, if (!isSelectKindSupported(SI)) continue; + LLVM_DEBUG({ + dbgs() << "New Select group with\n"; + for (auto SI : SIGroup) + dbgs() << " " << *SI.getI() << "\n"; + }); + SIGroups.push_back(SIGroup); } } diff --git a/llvm/test/CodeGen/AArch64/selectopt-not.ll b/llvm/test/CodeGen/AArch64/selectopt-not.ll index 7a949d11c80d..a7939d651a2c 100644 --- a/llvm/test/CodeGen/AArch64/selectopt-not.ll +++ b/llvm/test/CodeGen/AArch64/selectopt-not.ll @@ -1,5 +1,6 @@ ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py -; RUN: opt -select-optimize -mtriple=aarch64-linux-gnu -mcpu=neoverse-v2 -S < %s | FileCheck %s +; RUN: opt -select-optimize -mtriple=aarch64-linux-gnu -mcpu=neoverse-v2 -S < %s | FileCheck %s --check-prefixes=CHECK,CHECK-STANDARD +; RUN: opt -select-optimize -mtriple=aarch64-linux-gnu -mcpu=neoverse-v2 -S -disable-loop-level-heuristics < %s | FileCheck %s --check-prefixes=CHECK,CHECK-FORCED target datalayout = "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128-Fn32" target triple = "aarch64" @@ -29,10 +30,10 @@ define i32 @minloc1(ptr nocapture readonly %0, ptr nocapture readonly %1, ptr no ; CHECK-NEXT: [[TMP21:%.*]] = sub i64 0, [[TMP7]] ; CHECK-NEXT: br label [[DOTPREHEADER35:%.*]] ; CHECK: .preheader35: -; CHECK-NEXT: [[TMP22:%.*]] = phi i32 [ 2147483647, [[DOTPREHEADER35_LR_PH]] ], [ [[TMP30:%.*]], [[DOTPREHEADER35]] ] -; CHECK-NEXT: [[TMP23:%.*]] = phi i64 [ 0, [[DOTPREHEADER35_LR_PH]] ], [ [[IV_N:%.*]], [[DOTPREHEADER35]] ] -; CHECK-NEXT: [[DOT045:%.*]] = phi i1 [ false, [[DOTPREHEADER35_LR_PH]] ], [ [[DOT2:%.*]], [[DOTPREHEADER35]] ] -; CHECK-NEXT: [[DOTLCSSA364144:%.*]] = phi i32 [ 0, [[DOTPREHEADER35_LR_PH]] ], [ [[TMP29:%.*]], [[DOTPREHEADER35]] ] +; CHECK-NEXT: [[TMP22:%.*]] = phi i32 [ 2147483647, [[DOTPREHEADER35_LR_PH]] ], [ [[TMP30:%.*]], [[SELECT_END:%.*]] ] +; CHECK-NEXT: [[TMP23:%.*]] = phi i64 [ 0, [[DOTPREHEADER35_LR_PH]] ], [ [[IV_N:%.*]], [[SELECT_END]] ] +; CHECK-NEXT: [[DOT045:%.*]] = phi i1 [ false, [[DOTPREHEADER35_LR_PH]] ], [ [[DOT2:%.*]], [[SELECT_END]] ] +; CHECK-NEXT: [[DOTLCSSA364144:%.*]] = phi i32 [ 0, [[DOTPREHEADER35_LR_PH]] ], [ [[TMP29:%.*]], [[SELECT_END]] ] ; CHECK-NEXT: [[TMP24:%.*]] = mul nsw i64 [[TMP23]], [[TMP11]] ; CHECK-NEXT: [[TMP25:%.*]] = getelementptr i8, ptr [[TMP19]], i64 [[TMP24]] ; CHECK-NEXT: [[TMP26:%.*]] = load i32, ptr [[TMP25]], align 4 @@ -40,15 +41,20 @@ define i32 @minloc1(ptr nocapture readonly %0, ptr nocapture readonly %1, ptr no ; CHECK-NEXT: [[TMP28:%.*]] = icmp sge i32 [[TMP26]], [[TMP22]] ; CHECK-NEXT: [[DOTNOT33:%.*]] = and i1 [[DOT045]], [[TMP28]] ; CHECK-NEXT: [[OR_COND:%.*]] = select i1 [[TMP27]], i1 true, i1 [[DOTNOT33]] -; CHECK-NEXT: [[TMP29]] = select i1 [[OR_COND]], i32 [[DOTLCSSA364144]], i32 1 +; CHECK-NEXT: [[OR_COND_FROZEN:%.*]] = freeze i1 [[OR_COND]] +; CHECK-NEXT: br i1 [[OR_COND_FROZEN]], label [[SELECT_END]], label [[SELECT_FALSE:%.*]] +; CHECK: select.false: +; CHECK-NEXT: br label [[SELECT_END]] +; CHECK: select.end: +; CHECK-NEXT: [[TMP29]] = phi i32 [ [[DOTLCSSA364144]], [[DOTPREHEADER35]] ], [ 1, [[SELECT_FALSE]] ] +; CHECK-NEXT: [[DOT2]] = phi i1 [ [[DOT045]], [[DOTPREHEADER35]] ], [ true, [[SELECT_FALSE]] ] +; CHECK-NEXT: [[TMP30]] = phi i32 [ [[TMP22]], [[DOTPREHEADER35]] ], [ [[TMP20]], [[SELECT_FALSE]] ] ; CHECK-NEXT: [[NOT_OR_COND:%.*]] = xor i1 [[OR_COND]], true -; CHECK-NEXT: [[DOT2]] = select i1 [[NOT_OR_COND]], i1 true, i1 [[DOT045]] -; CHECK-NEXT: [[TMP30]] = select i1 [[OR_COND]], i32 [[TMP22]], i32 [[TMP20]] ; CHECK-NEXT: [[IV_N]] = add nuw nsw i64 [[TMP23]], 1 ; CHECK-NEXT: [[EXITCOND_NOT:%.*]] = icmp eq i64 [[IV_N]], [[TMP9]] ; CHECK-NEXT: br i1 [[EXITCOND_NOT]], label [[DOTPREHEADER]], label [[DOTPREHEADER35]] ; CHECK: .preheader: -; CHECK-NEXT: [[DOTLCSSA3641_LCSSA:%.*]] = phi i32 [ 0, [[TMP3:%.*]] ], [ [[TMP29]], [[DOTPREHEADER35]] ] +; CHECK-NEXT: [[DOTLCSSA3641_LCSSA:%.*]] = phi i32 [ 0, [[TMP3:%.*]] ], [ [[TMP29]], [[SELECT_END]] ] ; CHECK-NEXT: ret i32 [[DOTLCSSA3641_LCSSA]] ; %4 = getelementptr i8, ptr %0, i64 40 @@ -101,53 +107,106 @@ define i32 @minloc1(ptr nocapture readonly %0, ptr nocapture readonly %1, ptr no } define i32 @minloc1_otherunusednot(ptr nocapture readonly %0, ptr nocapture readonly %1, ptr nocapture readonly %2) { -; CHECK-LABEL: @minloc1_otherunusednot( -; CHECK-NEXT: [[TMP4:%.*]] = getelementptr i8, ptr [[TMP0:%.*]], i64 40 -; CHECK-NEXT: [[TMP5:%.*]] = load i64, ptr [[TMP4]], align 8 -; CHECK-NEXT: [[TMP6:%.*]] = getelementptr i8, ptr [[TMP0]], i64 64 -; CHECK-NEXT: [[TMP7:%.*]] = load i64, ptr [[TMP6]], align 8 -; CHECK-NEXT: [[TMP8:%.*]] = getelementptr i8, ptr [[TMP0]], i64 80 -; CHECK-NEXT: [[TMP9:%.*]] = load i64, ptr [[TMP8]], align 8 -; CHECK-NEXT: [[TMP10:%.*]] = getelementptr i8, ptr [[TMP0]], i64 88 -; CHECK-NEXT: [[TMP11:%.*]] = load i64, ptr [[TMP10]], align 8 -; CHECK-NEXT: [[TMP12:%.*]] = load ptr, ptr [[TMP0]], align 8 -; CHECK-NEXT: [[TMP13:%.*]] = load i32, ptr [[TMP1:%.*]], align 4 -; CHECK-NEXT: [[TMP14:%.*]] = sext i32 [[TMP13]] to i64 -; CHECK-NEXT: [[TMP15:%.*]] = add nsw i64 [[TMP14]], -1 -; CHECK-NEXT: [[TMP16:%.*]] = mul i64 [[TMP15]], [[TMP5]] -; CHECK-NEXT: [[TMP17:%.*]] = getelementptr i8, ptr [[TMP12]], i64 [[TMP16]] -; CHECK-NEXT: [[TMP18:%.*]] = shl i64 [[TMP7]], 3 -; CHECK-NEXT: [[TMP19:%.*]] = getelementptr i8, ptr [[TMP17]], i64 [[TMP18]] -; CHECK-NEXT: [[TMP20:%.*]] = load i32, ptr [[TMP2:%.*]], align 4 -; CHECK-NEXT: [[DOTNOT:%.*]] = icmp slt i64 [[TMP9]], 1 -; CHECK-NEXT: br i1 [[DOTNOT]], label [[DOTPREHEADER:%.*]], label [[DOTPREHEADER35_LR_PH:%.*]] -; CHECK: .preheader35.lr.ph: -; CHECK-NEXT: [[TMP21:%.*]] = sub i64 0, [[TMP7]] -; CHECK-NEXT: br label [[DOTPREHEADER35:%.*]] -; CHECK: .preheader35: -; CHECK-NEXT: [[TMP22:%.*]] = phi i32 [ 2147483647, [[DOTPREHEADER35_LR_PH]] ], [ [[TMP30:%.*]], [[DOTPREHEADER35]] ] -; CHECK-NEXT: [[TMP23:%.*]] = phi i64 [ 0, [[DOTPREHEADER35_LR_PH]] ], [ [[IV_N:%.*]], [[DOTPREHEADER35]] ] -; CHECK-NEXT: [[DOT045:%.*]] = phi i1 [ false, [[DOTPREHEADER35_LR_PH]] ], [ [[DOT2:%.*]], [[DOTPREHEADER35]] ] -; CHECK-NEXT: [[DOTLCSSA364144:%.*]] = phi i32 [ 0, [[DOTPREHEADER35_LR_PH]] ], [ [[TMP29:%.*]], [[DOTPREHEADER35]] ] -; CHECK-NEXT: [[TMP24:%.*]] = mul nsw i64 [[TMP23]], [[TMP11]] -; CHECK-NEXT: [[TMP25:%.*]] = getelementptr i8, ptr [[TMP19]], i64 [[TMP24]] -; CHECK-NEXT: [[TMP26:%.*]] = load i32, ptr [[TMP25]], align 4 -; CHECK-NEXT: [[TMP27:%.*]] = icmp ne i32 [[TMP26]], [[TMP20]] -; CHECK-NEXT: [[TMP28:%.*]] = icmp sge i32 [[TMP26]], [[TMP22]] -; CHECK-NEXT: [[DOTNOT33:%.*]] = and i1 [[DOT045]], [[TMP28]] -; CHECK-NEXT: [[OR_COND:%.*]] = select i1 [[TMP27]], i1 true, i1 [[DOTNOT33]] -; CHECK-NEXT: [[TMP29]] = select i1 [[OR_COND]], i32 [[DOTLCSSA364144]], i32 1 -; CHECK-NEXT: [[DOT2]] = select i1 [[OR_COND]], i1 [[DOT045]], i1 true -; CHECK-NEXT: [[NOT_OR_COND:%.*]] = xor i1 [[OR_COND]], true -; CHECK-NEXT: [[TMP30]] = select i1 [[OR_COND]], i32 [[TMP22]], i32 [[TMP20]] -; CHECK-NEXT: [[IV_N]] = add nuw nsw i64 [[TMP23]], 1 -; CHECK-NEXT: [[EXITCOND_NOT:%.*]] = icmp eq i64 [[IV_N]], [[TMP9]] -; CHECK-NEXT: br i1 [[EXITCOND_NOT]], label [[DOTPREHEADER]], label [[DOTPREHEADER35]] -; CHECK: .preheader: -; CHECK-NEXT: [[DOTLCSSA3641_LCSSA:%.*]] = phi i32 [ 0, [[TMP3:%.*]] ], [ [[TMP29]], [[DOTPREHEADER35]] ] -; CHECK-NEXT: [[P:%.*]] = phi i1 [ false, [[TMP3]] ], [ [[NOT_OR_COND]], [[DOTPREHEADER35]] ] -; CHECK-NEXT: [[Q:%.*]] = select i1 [[P]], i32 [[DOTLCSSA3641_LCSSA]], i32 1 -; CHECK-NEXT: ret i32 [[Q]] +; CHECK-STANDARD-LABEL: @minloc1_otherunusednot( +; CHECK-STANDARD-NEXT: [[TMP4:%.*]] = getelementptr i8, ptr [[TMP0:%.*]], i64 40 +; CHECK-STANDARD-NEXT: [[TMP5:%.*]] = load i64, ptr [[TMP4]], align 8 +; CHECK-STANDARD-NEXT: [[TMP6:%.*]] = getelementptr i8, ptr [[TMP0]], i64 64 +; CHECK-STANDARD-NEXT: [[TMP7:%.*]] = load i64, ptr [[TMP6]], align 8 +; CHECK-STANDARD-NEXT: [[TMP8:%.*]] = getelementptr i8, ptr [[TMP0]], i64 80 +; CHECK-STANDARD-NEXT: [[TMP9:%.*]] = load i64, ptr [[TMP8]], align 8 +; CHECK-STANDARD-NEXT: [[TMP10:%.*]] = getelementptr i8, ptr [[TMP0]], i64 88 +; CHECK-STANDARD-NEXT: [[TMP11:%.*]] = load i64, ptr [[TMP10]], align 8 +; CHECK-STANDARD-NEXT: [[TMP12:%.*]] = load ptr, ptr [[TMP0]], align 8 +; CHECK-STANDARD-NEXT: [[TMP13:%.*]] = load i32, ptr [[TMP1:%.*]], align 4 +; CHECK-STANDARD-NEXT: [[TMP14:%.*]] = sext i32 [[TMP13]] to i64 +; CHECK-STANDARD-NEXT: [[TMP15:%.*]] = add nsw i64 [[TMP14]], -1 +; CHECK-STANDARD-NEXT: [[TMP16:%.*]] = mul i64 [[TMP15]], [[TMP5]] +; CHECK-STANDARD-NEXT: [[TMP17:%.*]] = getelementptr i8, ptr [[TMP12]], i64 [[TMP16]] +; CHECK-STANDARD-NEXT: [[TMP18:%.*]] = shl i64 [[TMP7]], 3 +; CHECK-STANDARD-NEXT: [[TMP19:%.*]] = getelementptr i8, ptr [[TMP17]], i64 [[TMP18]] +; CHECK-STANDARD-NEXT: [[TMP20:%.*]] = load i32, ptr [[TMP2:%.*]], align 4 +; CHECK-STANDARD-NEXT: [[DOTNOT:%.*]] = icmp slt i64 [[TMP9]], 1 +; CHECK-STANDARD-NEXT: br i1 [[DOTNOT]], label [[DOTPREHEADER:%.*]], label [[DOTPREHEADER35_LR_PH:%.*]] +; CHECK-STANDARD: .preheader35.lr.ph: +; CHECK-STANDARD-NEXT: [[TMP21:%.*]] = sub i64 0, [[TMP7]] +; CHECK-STANDARD-NEXT: br label [[DOTPREHEADER35:%.*]] +; CHECK-STANDARD: .preheader35: +; CHECK-STANDARD-NEXT: [[TMP22:%.*]] = phi i32 [ 2147483647, [[DOTPREHEADER35_LR_PH]] ], [ [[TMP30:%.*]], [[DOTPREHEADER35]] ] +; CHECK-STANDARD-NEXT: [[TMP23:%.*]] = phi i64 [ 0, [[DOTPREHEADER35_LR_PH]] ], [ [[IV_N:%.*]], [[DOTPREHEADER35]] ] +; CHECK-STANDARD-NEXT: [[DOT045:%.*]] = phi i1 [ false, [[DOTPREHEADER35_LR_PH]] ], [ [[DOT2:%.*]], [[DOTPREHEADER35]] ] +; CHECK-STANDARD-NEXT: [[DOTLCSSA364144:%.*]] = phi i32 [ 0, [[DOTPREHEADER35_LR_PH]] ], [ [[TMP29:%.*]], [[DOTPREHEADER35]] ] +; CHECK-STANDARD-NEXT: [[TMP24:%.*]] = mul nsw i64 [[TMP23]], [[TMP11]] +; CHECK-STANDARD-NEXT: [[TMP25:%.*]] = getelementptr i8, ptr [[TMP19]], i64 [[TMP24]] +; CHECK-STANDARD-NEXT: [[TMP26:%.*]] = load i32, ptr [[TMP25]], align 4 +; CHECK-STANDARD-NEXT: [[TMP27:%.*]] = icmp ne i32 [[TMP26]], [[TMP20]] +; CHECK-STANDARD-NEXT: [[TMP28:%.*]] = icmp sge i32 [[TMP26]], [[TMP22]] +; CHECK-STANDARD-NEXT: [[DOTNOT33:%.*]] = and i1 [[DOT045]], [[TMP28]] +; CHECK-STANDARD-NEXT: [[OR_COND:%.*]] = select i1 [[TMP27]], i1 true, i1 [[DOTNOT33]] +; CHECK-STANDARD-NEXT: [[TMP29]] = select i1 [[OR_COND]], i32 [[DOTLCSSA364144]], i32 1 +; CHECK-STANDARD-NEXT: [[DOT2]] = select i1 [[OR_COND]], i1 [[DOT045]], i1 true +; CHECK-STANDARD-NEXT: [[NOT_OR_COND:%.*]] = xor i1 [[OR_COND]], true +; CHECK-STANDARD-NEXT: [[TMP30]] = select i1 [[OR_COND]], i32 [[TMP22]], i32 [[TMP20]] +; CHECK-STANDARD-NEXT: [[IV_N]] = add nuw nsw i64 [[TMP23]], 1 +; CHECK-STANDARD-NEXT: [[EXITCOND_NOT:%.*]] = icmp eq i64 [[IV_N]], [[TMP9]] +; CHECK-STANDARD-NEXT: br i1 [[EXITCOND_NOT]], label [[DOTPREHEADER]], label [[DOTPREHEADER35]] +; CHECK-STANDARD: .preheader: +; CHECK-STANDARD-NEXT: [[DOTLCSSA3641_LCSSA:%.*]] = phi i32 [ 0, [[TMP3:%.*]] ], [ [[TMP29]], [[DOTPREHEADER35]] ] +; CHECK-STANDARD-NEXT: [[P:%.*]] = phi i1 [ false, [[TMP3]] ], [ [[NOT_OR_COND]], [[DOTPREHEADER35]] ] +; CHECK-STANDARD-NEXT: [[Q:%.*]] = select i1 [[P]], i32 [[DOTLCSSA3641_LCSSA]], i32 1 +; CHECK-STANDARD-NEXT: ret i32 [[Q]] +; +; CHECK-FORCED-LABEL: @minloc1_otherunusednot( +; CHECK-FORCED-NEXT: [[TMP4:%.*]] = getelementptr i8, ptr [[TMP0:%.*]], i64 40 +; CHECK-FORCED-NEXT: [[TMP5:%.*]] = load i64, ptr [[TMP4]], align 8 +; CHECK-FORCED-NEXT: [[TMP6:%.*]] = getelementptr i8, ptr [[TMP0]], i64 64 +; CHECK-FORCED-NEXT: [[TMP7:%.*]] = load i64, ptr [[TMP6]], align 8 +; CHECK-FORCED-NEXT: [[TMP8:%.*]] = getelementptr i8, ptr [[TMP0]], i64 80 +; CHECK-FORCED-NEXT: [[TMP9:%.*]] = load i64, ptr [[TMP8]], align 8 +; CHECK-FORCED-NEXT: [[TMP10:%.*]] = getelementptr i8, ptr [[TMP0]], i64 88 +; CHECK-FORCED-NEXT: [[TMP11:%.*]] = load i64, ptr [[TMP10]], align 8 +; CHECK-FORCED-NEXT: [[TMP12:%.*]] = load ptr, ptr [[TMP0]], align 8 +; CHECK-FORCED-NEXT: [[TMP13:%.*]] = load i32, ptr [[TMP1:%.*]], align 4 +; CHECK-FORCED-NEXT: [[TMP14:%.*]] = sext i32 [[TMP13]] to i64 +; CHECK-FORCED-NEXT: [[TMP15:%.*]] = add nsw i64 [[TMP14]], -1 +; CHECK-FORCED-NEXT: [[TMP16:%.*]] = mul i64 [[TMP15]], [[TMP5]] +; CHECK-FORCED-NEXT: [[TMP17:%.*]] = getelementptr i8, ptr [[TMP12]], i64 [[TMP16]] +; CHECK-FORCED-NEXT: [[TMP18:%.*]] = shl i64 [[TMP7]], 3 +; CHECK-FORCED-NEXT: [[TMP19:%.*]] = getelementptr i8, ptr [[TMP17]], i64 [[TMP18]] +; CHECK-FORCED-NEXT: [[TMP20:%.*]] = load i32, ptr [[TMP2:%.*]], align 4 +; CHECK-FORCED-NEXT: [[DOTNOT:%.*]] = icmp slt i64 [[TMP9]], 1 +; CHECK-FORCED-NEXT: br i1 [[DOTNOT]], label [[DOTPREHEADER:%.*]], label [[DOTPREHEADER35_LR_PH:%.*]] +; CHECK-FORCED: .preheader35.lr.ph: +; CHECK-FORCED-NEXT: [[TMP21:%.*]] = sub i64 0, [[TMP7]] +; CHECK-FORCED-NEXT: br label [[DOTPREHEADER35:%.*]] +; CHECK-FORCED: .preheader35: +; CHECK-FORCED-NEXT: [[TMP22:%.*]] = phi i32 [ 2147483647, [[DOTPREHEADER35_LR_PH]] ], [ [[TMP30:%.*]], [[SELECT_END:%.*]] ] +; CHECK-FORCED-NEXT: [[TMP23:%.*]] = phi i64 [ 0, [[DOTPREHEADER35_LR_PH]] ], [ [[IV_N:%.*]], [[SELECT_END]] ] +; CHECK-FORCED-NEXT: [[DOT045:%.*]] = phi i1 [ false, [[DOTPREHEADER35_LR_PH]] ], [ [[DOT2:%.*]], [[SELECT_END]] ] +; CHECK-FORCED-NEXT: [[DOTLCSSA364144:%.*]] = phi i32 [ 0, [[DOTPREHEADER35_LR_PH]] ], [ [[TMP29:%.*]], [[SELECT_END]] ] +; CHECK-FORCED-NEXT: [[TMP24:%.*]] = mul nsw i64 [[TMP23]], [[TMP11]] +; CHECK-FORCED-NEXT: [[TMP25:%.*]] = getelementptr i8, ptr [[TMP19]], i64 [[TMP24]] +; CHECK-FORCED-NEXT: [[TMP26:%.*]] = load i32, ptr [[TMP25]], align 4 +; CHECK-FORCED-NEXT: [[TMP27:%.*]] = icmp ne i32 [[TMP26]], [[TMP20]] +; CHECK-FORCED-NEXT: [[TMP28:%.*]] = icmp sge i32 [[TMP26]], [[TMP22]] +; CHECK-FORCED-NEXT: [[DOTNOT33:%.*]] = and i1 [[DOT045]], [[TMP28]] +; CHECK-FORCED-NEXT: [[OR_COND:%.*]] = select i1 [[TMP27]], i1 true, i1 [[DOTNOT33]] +; CHECK-FORCED-NEXT: [[OR_COND_FROZEN:%.*]] = freeze i1 [[OR_COND]] +; CHECK-FORCED-NEXT: br i1 [[OR_COND_FROZEN]], label [[SELECT_END]], label [[SELECT_FALSE:%.*]] +; CHECK-FORCED: select.false: +; CHECK-FORCED-NEXT: br label [[SELECT_END]] +; CHECK-FORCED: select.end: +; CHECK-FORCED-NEXT: [[TMP29]] = phi i32 [ [[DOTLCSSA364144]], [[DOTPREHEADER35]] ], [ 1, [[SELECT_FALSE]] ] +; CHECK-FORCED-NEXT: [[DOT2]] = phi i1 [ [[DOT045]], [[DOTPREHEADER35]] ], [ true, [[SELECT_FALSE]] ] +; CHECK-FORCED-NEXT: [[TMP30]] = phi i32 [ [[TMP22]], [[DOTPREHEADER35]] ], [ [[TMP20]], [[SELECT_FALSE]] ] +; CHECK-FORCED-NEXT: [[NOT_OR_COND:%.*]] = xor i1 [[OR_COND]], true +; CHECK-FORCED-NEXT: [[IV_N]] = add nuw nsw i64 [[TMP23]], 1 +; CHECK-FORCED-NEXT: [[EXITCOND_NOT:%.*]] = icmp eq i64 [[IV_N]], [[TMP9]] +; CHECK-FORCED-NEXT: br i1 [[EXITCOND_NOT]], label [[DOTPREHEADER]], label [[DOTPREHEADER35]] +; CHECK-FORCED: .preheader: +; CHECK-FORCED-NEXT: [[DOTLCSSA3641_LCSSA:%.*]] = phi i32 [ 0, [[TMP3:%.*]] ], [ [[TMP29]], [[SELECT_END]] ] +; CHECK-FORCED-NEXT: [[P:%.*]] = phi i1 [ false, [[TMP3]] ], [ [[NOT_OR_COND]], [[SELECT_END]] ] +; CHECK-FORCED-NEXT: [[Q:%.*]] = select i1 [[P]], i32 [[DOTLCSSA3641_LCSSA]], i32 1 +; CHECK-FORCED-NEXT: ret i32 [[Q]] ; %4 = getelementptr i8, ptr %0, i64 40 %5 = load i64, ptr %4, align 8 @@ -225,10 +284,10 @@ define i32 @minloc1_twonot(ptr nocapture readonly %0, ptr nocapture readonly %1, ; CHECK-NEXT: [[TMP21:%.*]] = sub i64 0, [[TMP7]] ; CHECK-NEXT: br label [[DOTPREHEADER35:%.*]] ; CHECK: .preheader35: -; CHECK-NEXT: [[TMP22:%.*]] = phi i32 [ 2147483647, [[DOTPREHEADER35_LR_PH]] ], [ [[TMP30:%.*]], [[DOTPREHEADER35]] ] -; CHECK-NEXT: [[TMP23:%.*]] = phi i64 [ 0, [[DOTPREHEADER35_LR_PH]] ], [ [[IV_N:%.*]], [[DOTPREHEADER35]] ] -; CHECK-NEXT: [[DOT045:%.*]] = phi i1 [ false, [[DOTPREHEADER35_LR_PH]] ], [ [[DOT3:%.*]], [[DOTPREHEADER35]] ] -; CHECK-NEXT: [[DOTLCSSA364144:%.*]] = phi i32 [ 0, [[DOTPREHEADER35_LR_PH]] ], [ [[TMP29:%.*]], [[DOTPREHEADER35]] ] +; CHECK-NEXT: [[TMP22:%.*]] = phi i32 [ 2147483647, [[DOTPREHEADER35_LR_PH]] ], [ [[TMP30:%.*]], [[SELECT_END:%.*]] ] +; CHECK-NEXT: [[TMP23:%.*]] = phi i64 [ 0, [[DOTPREHEADER35_LR_PH]] ], [ [[IV_N:%.*]], [[SELECT_END]] ] +; CHECK-NEXT: [[DOT045:%.*]] = phi i1 [ false, [[DOTPREHEADER35_LR_PH]] ], [ [[DOT3:%.*]], [[SELECT_END]] ] +; CHECK-NEXT: [[DOTLCSSA364144:%.*]] = phi i32 [ 0, [[DOTPREHEADER35_LR_PH]] ], [ [[TMP29:%.*]], [[SELECT_END]] ] ; CHECK-NEXT: [[TMP24:%.*]] = mul nsw i64 [[TMP23]], [[TMP11]] ; CHECK-NEXT: [[TMP25:%.*]] = getelementptr i8, ptr [[TMP19]], i64 [[TMP24]] ; CHECK-NEXT: [[TMP26:%.*]] = load i32, ptr [[TMP25]], align 4 @@ -236,16 +295,21 @@ define i32 @minloc1_twonot(ptr nocapture readonly %0, ptr nocapture readonly %1, ; CHECK-NEXT: [[TMP28:%.*]] = icmp sge i32 [[TMP26]], [[TMP22]] ; CHECK-NEXT: [[DOTNOT33:%.*]] = and i1 [[DOT045]], [[TMP28]] ; CHECK-NEXT: [[OR_COND:%.*]] = select i1 [[TMP27]], i1 true, i1 [[DOTNOT33]] -; CHECK-NEXT: [[TMP29]] = select i1 [[OR_COND]], i32 [[DOTLCSSA364144]], i32 1 +; CHECK-NEXT: [[OR_COND_FROZEN:%.*]] = freeze i1 [[OR_COND]] +; CHECK-NEXT: br i1 [[OR_COND_FROZEN]], label [[SELECT_END]], label [[SELECT_FALSE:%.*]] +; CHECK: select.false: +; CHECK-NEXT: br label [[SELECT_END]] +; CHECK: select.end: +; CHECK-NEXT: [[TMP29]] = phi i32 [ [[DOTLCSSA364144]], [[DOTPREHEADER35]] ], [ 1, [[SELECT_FALSE]] ] +; CHECK-NEXT: [[DOT2:%.*]] = phi i1 [ [[DOT045]], [[DOTPREHEADER35]] ], [ true, [[SELECT_FALSE]] ] +; CHECK-NEXT: [[DOT3]] = phi i1 [ [[DOT045]], [[DOTPREHEADER35]] ], [ true, [[SELECT_FALSE]] ] +; CHECK-NEXT: [[TMP30]] = phi i32 [ [[TMP22]], [[DOTPREHEADER35]] ], [ [[TMP20]], [[SELECT_FALSE]] ] ; CHECK-NEXT: [[NOT_OR_COND:%.*]] = xor i1 [[OR_COND]], true -; CHECK-NEXT: [[DOT2:%.*]] = select i1 [[NOT_OR_COND]], i1 true, i1 [[DOT045]] -; CHECK-NEXT: [[DOT3]] = select i1 [[NOT_OR_COND]], i1 true, i1 [[DOT2]] -; CHECK-NEXT: [[TMP30]] = select i1 [[OR_COND]], i32 [[TMP22]], i32 [[TMP20]] ; CHECK-NEXT: [[IV_N]] = add nuw nsw i64 [[TMP23]], 1 ; CHECK-NEXT: [[EXITCOND_NOT:%.*]] = icmp eq i64 [[IV_N]], [[TMP9]] ; CHECK-NEXT: br i1 [[EXITCOND_NOT]], label [[DOTPREHEADER]], label [[DOTPREHEADER35]] ; CHECK: .preheader: -; CHECK-NEXT: [[DOTLCSSA3641_LCSSA:%.*]] = phi i32 [ 0, [[TMP3:%.*]] ], [ [[TMP29]], [[DOTPREHEADER35]] ] +; CHECK-NEXT: [[DOTLCSSA3641_LCSSA:%.*]] = phi i32 [ 0, [[TMP3:%.*]] ], [ [[TMP29]], [[SELECT_END]] ] ; CHECK-NEXT: ret i32 [[DOTLCSSA3641_LCSSA]] ; %4 = getelementptr i8, ptr %0, i64 40 @@ -323,10 +387,10 @@ define i32 @minloc1_onenotdependent(ptr nocapture readonly %0, ptr nocapture rea ; CHECK-NEXT: [[TMP21:%.*]] = sub i64 0, [[TMP7]] ; CHECK-NEXT: br label [[DOTPREHEADER35:%.*]] ; CHECK: .preheader35: -; CHECK-NEXT: [[TMP22:%.*]] = phi i32 [ 2147483647, [[DOTPREHEADER35_LR_PH]] ], [ [[TMP30:%.*]], [[DOTPREHEADER35]] ] -; CHECK-NEXT: [[TMP23:%.*]] = phi i64 [ 0, [[DOTPREHEADER35_LR_PH]] ], [ [[IV_N:%.*]], [[DOTPREHEADER35]] ] -; CHECK-NEXT: [[DOT045:%.*]] = phi i1 [ false, [[DOTPREHEADER35_LR_PH]] ], [ [[DOT3:%.*]], [[DOTPREHEADER35]] ] -; CHECK-NEXT: [[DOTLCSSA364144:%.*]] = phi i32 [ 0, [[DOTPREHEADER35_LR_PH]] ], [ [[TMP29:%.*]], [[DOTPREHEADER35]] ] +; CHECK-NEXT: [[TMP22:%.*]] = phi i32 [ 2147483647, [[DOTPREHEADER35_LR_PH]] ], [ [[TMP30:%.*]], [[SELECT_END:%.*]] ] +; CHECK-NEXT: [[TMP23:%.*]] = phi i64 [ 0, [[DOTPREHEADER35_LR_PH]] ], [ [[IV_N:%.*]], [[SELECT_END]] ] +; CHECK-NEXT: [[DOT045:%.*]] = phi i1 [ false, [[DOTPREHEADER35_LR_PH]] ], [ [[DOT3:%.*]], [[SELECT_END]] ] +; CHECK-NEXT: [[DOTLCSSA364144:%.*]] = phi i32 [ 0, [[DOTPREHEADER35_LR_PH]] ], [ [[TMP29:%.*]], [[SELECT_END]] ] ; CHECK-NEXT: [[TMP24:%.*]] = mul nsw i64 [[TMP23]], [[TMP11]] ; CHECK-NEXT: [[TMP25:%.*]] = getelementptr i8, ptr [[TMP19]], i64 [[TMP24]] ; CHECK-NEXT: [[TMP26:%.*]] = load i32, ptr [[TMP25]], align 4 @@ -334,16 +398,21 @@ define i32 @minloc1_onenotdependent(ptr nocapture readonly %0, ptr nocapture rea ; CHECK-NEXT: [[TMP28:%.*]] = icmp sge i32 [[TMP26]], [[TMP22]] ; CHECK-NEXT: [[DOTNOT33:%.*]] = and i1 [[DOT045]], [[TMP28]] ; CHECK-NEXT: [[OR_COND:%.*]] = select i1 [[TMP27]], i1 true, i1 [[DOTNOT33]] -; CHECK-NEXT: [[TMP29]] = select i1 [[OR_COND]], i32 [[DOTLCSSA364144]], i32 1 +; CHECK-NEXT: [[OR_COND_FROZEN:%.*]] = freeze i1 [[OR_COND]] +; CHECK-NEXT: br i1 [[OR_COND_FROZEN]], label [[SELECT_END]], label [[SELECT_FALSE:%.*]] +; CHECK: select.false: +; CHECK-NEXT: br label [[SELECT_END]] +; CHECK: select.end: +; CHECK-NEXT: [[TMP29]] = phi i32 [ [[DOTLCSSA364144]], [[DOTPREHEADER35]] ], [ 1, [[SELECT_FALSE]] ] +; CHECK-NEXT: [[DOT2:%.*]] = phi i1 [ true, [[DOTPREHEADER35]] ], [ [[DOT045]], [[SELECT_FALSE]] ] +; CHECK-NEXT: [[DOT3]] = phi i1 [ true, [[DOTPREHEADER35]] ], [ true, [[SELECT_FALSE]] ] +; CHECK-NEXT: [[TMP30]] = phi i32 [ [[TMP22]], [[DOTPREHEADER35]] ], [ [[TMP20]], [[SELECT_FALSE]] ] ; CHECK-NEXT: [[NOT_OR_COND:%.*]] = xor i1 [[OR_COND]], true -; CHECK-NEXT: [[DOT2:%.*]] = select i1 [[OR_COND]], i1 true, i1 [[DOT045]] -; CHECK-NEXT: [[DOT3]] = select i1 [[NOT_OR_COND]], i1 true, i1 [[DOT2]] -; CHECK-NEXT: [[TMP30]] = select i1 [[OR_COND]], i32 [[TMP22]], i32 [[TMP20]] ; CHECK-NEXT: [[IV_N]] = add nuw nsw i64 [[TMP23]], 1 ; CHECK-NEXT: [[EXITCOND_NOT:%.*]] = icmp eq i64 [[IV_N]], [[TMP9]] ; CHECK-NEXT: br i1 [[EXITCOND_NOT]], label [[DOTPREHEADER]], label [[DOTPREHEADER35]] ; CHECK: .preheader: -; CHECK-NEXT: [[DOTLCSSA3641_LCSSA:%.*]] = phi i32 [ 0, [[TMP3:%.*]] ], [ [[TMP29]], [[DOTPREHEADER35]] ] +; CHECK-NEXT: [[DOTLCSSA3641_LCSSA:%.*]] = phi i32 [ 0, [[TMP3:%.*]] ], [ [[TMP29]], [[SELECT_END]] ] ; CHECK-NEXT: ret i32 [[DOTLCSSA3641_LCSSA]] ; %4 = getelementptr i8, ptr %0, i64 40 @@ -429,10 +498,10 @@ define i32 @minloc9(ptr nocapture readonly %0, ptr nocapture readonly %1, ptr no ; CHECK-NEXT: [[DOTNEG55:%.*]] = mul i64 [[TMP7]], -8 ; CHECK-NEXT: br label [[DOTPREHEADER35:%.*]] ; CHECK: .preheader35: -; CHECK-NEXT: [[TMP22:%.*]] = phi i32 [ 2147483647, [[DOTPREHEADER35_LR_PH]] ], [ [[TMP78:%.*]], [[DOTPREHEADER35]] ] -; CHECK-NEXT: [[TMP23:%.*]] = phi i64 [ 0, [[DOTPREHEADER35_LR_PH]] ], [ [[TMP79:%.*]], [[DOTPREHEADER35]] ] -; CHECK-NEXT: [[DOT045:%.*]] = phi i1 [ false, [[DOTPREHEADER35_LR_PH]] ], [ [[DOT2_8:%.*]], [[DOTPREHEADER35]] ] -; CHECK-NEXT: [[DOTLCSSA364144:%.*]] = phi i32 [ 0, [[DOTPREHEADER35_LR_PH]] ], [ [[TMP77:%.*]], [[DOTPREHEADER35]] ] +; CHECK-NEXT: [[TMP22:%.*]] = phi i32 [ 2147483647, [[DOTPREHEADER35_LR_PH]] ], [ [[TMP78:%.*]], [[SELECT_END15:%.*]] ] +; CHECK-NEXT: [[TMP23:%.*]] = phi i64 [ 0, [[DOTPREHEADER35_LR_PH]] ], [ [[TMP79:%.*]], [[SELECT_END15]] ] +; CHECK-NEXT: [[DOT045:%.*]] = phi i1 [ false, [[DOTPREHEADER35_LR_PH]] ], [ [[DOT2_8:%.*]], [[SELECT_END15]] ] +; CHECK-NEXT: [[DOTLCSSA364144:%.*]] = phi i32 [ 0, [[DOTPREHEADER35_LR_PH]] ], [ [[TMP77:%.*]], [[SELECT_END15]] ] ; CHECK-NEXT: [[TMP24:%.*]] = mul nsw i64 [[TMP23]], [[TMP11]] ; CHECK-NEXT: [[TMP25:%.*]] = getelementptr i8, ptr [[TMP19]], i64 [[TMP24]] ; CHECK-NEXT: [[TMP26:%.*]] = load i32, ptr [[TMP25]], align 4 @@ -440,95 +509,140 @@ define i32 @minloc9(ptr nocapture readonly %0, ptr nocapture readonly %1, ptr no ; CHECK-NEXT: [[TMP28:%.*]] = icmp sge i32 [[TMP26]], [[TMP22]] ; CHECK-NEXT: [[DOTNOT33:%.*]] = and i1 [[DOT045]], [[TMP28]] ; CHECK-NEXT: [[OR_COND:%.*]] = select i1 [[TMP27]], i1 true, i1 [[DOTNOT33]] -; CHECK-NEXT: [[TMP29:%.*]] = select i1 [[OR_COND]], i32 [[DOTLCSSA364144]], i32 1 +; CHECK-NEXT: [[OR_COND_FROZEN:%.*]] = freeze i1 [[OR_COND]] +; CHECK-NEXT: br i1 [[OR_COND_FROZEN]], label [[SELECT_END:%.*]], label [[SELECT_FALSE:%.*]] +; CHECK: select.false: +; CHECK-NEXT: br label [[SELECT_END]] +; CHECK: select.end: +; CHECK-NEXT: [[TMP29:%.*]] = phi i32 [ [[DOTLCSSA364144]], [[DOTPREHEADER35]] ], [ 1, [[SELECT_FALSE]] ] +; CHECK-NEXT: [[DOT2:%.*]] = phi i1 [ [[DOT045]], [[DOTPREHEADER35]] ], [ true, [[SELECT_FALSE]] ] +; CHECK-NEXT: [[TMP30:%.*]] = phi i32 [ [[TMP22]], [[DOTPREHEADER35]] ], [ [[TMP20]], [[SELECT_FALSE]] ] ; CHECK-NEXT: [[NOT_OR_COND:%.*]] = xor i1 [[OR_COND]], true -; CHECK-NEXT: [[DOT2:%.*]] = select i1 [[NOT_OR_COND]], i1 true, i1 [[DOT045]] -; CHECK-NEXT: [[TMP30:%.*]] = select i1 [[OR_COND]], i32 [[TMP22]], i32 [[TMP20]] ; CHECK-NEXT: [[TMP31:%.*]] = getelementptr i8, ptr [[TMP25]], i64 [[TMP21]] ; CHECK-NEXT: [[TMP32:%.*]] = load i32, ptr [[TMP31]], align 4 ; CHECK-NEXT: [[TMP33:%.*]] = icmp ne i32 [[TMP32]], [[TMP20]] ; CHECK-NEXT: [[TMP34:%.*]] = icmp sge i32 [[TMP32]], [[TMP30]] ; CHECK-NEXT: [[DOTNOT33_1:%.*]] = and i1 [[DOT2]], [[TMP34]] ; CHECK-NEXT: [[OR_COND_1:%.*]] = select i1 [[TMP33]], i1 true, i1 [[DOTNOT33_1]] -; CHECK-NEXT: [[TMP35:%.*]] = select i1 [[OR_COND_1]], i32 [[TMP29]], i32 2 +; CHECK-NEXT: [[OR_COND_1_FROZEN:%.*]] = freeze i1 [[OR_COND_1]] +; CHECK-NEXT: br i1 [[OR_COND_1_FROZEN]], label [[SELECT_END1:%.*]], label [[SELECT_FALSE2:%.*]] +; CHECK: select.false2: +; CHECK-NEXT: br label [[SELECT_END1]] +; CHECK: select.end1: +; CHECK-NEXT: [[TMP35:%.*]] = phi i32 [ [[TMP29]], [[SELECT_END]] ], [ 2, [[SELECT_FALSE2]] ] +; CHECK-NEXT: [[DOT2_1:%.*]] = phi i1 [ [[DOT2]], [[SELECT_END]] ], [ true, [[SELECT_FALSE2]] ] +; CHECK-NEXT: [[TMP36:%.*]] = phi i32 [ [[TMP30]], [[SELECT_END]] ], [ [[TMP20]], [[SELECT_FALSE2]] ] ; CHECK-NEXT: [[NOT_OR_COND_1:%.*]] = xor i1 [[OR_COND_1]], true -; CHECK-NEXT: [[DOT2_1:%.*]] = select i1 [[NOT_OR_COND_1]], i1 true, i1 [[DOT2]] -; CHECK-NEXT: [[TMP36:%.*]] = select i1 [[OR_COND_1]], i32 [[TMP30]], i32 [[TMP20]] ; CHECK-NEXT: [[TMP37:%.*]] = getelementptr i8, ptr [[TMP25]], i64 [[DOTNEG]] ; CHECK-NEXT: [[TMP38:%.*]] = load i32, ptr [[TMP37]], align 4 ; CHECK-NEXT: [[TMP39:%.*]] = icmp ne i32 [[TMP38]], [[TMP20]] ; CHECK-NEXT: [[TMP40:%.*]] = icmp sge i32 [[TMP38]], [[TMP36]] ; CHECK-NEXT: [[DOTNOT33_2:%.*]] = and i1 [[DOT2_1]], [[TMP40]] ; CHECK-NEXT: [[OR_COND_2:%.*]] = select i1 [[TMP39]], i1 true, i1 [[DOTNOT33_2]] -; CHECK-NEXT: [[TMP41:%.*]] = select i1 [[OR_COND_2]], i32 [[TMP35]], i32 3 +; CHECK-NEXT: [[OR_COND_2_FROZEN:%.*]] = freeze i1 [[OR_COND_2]] +; CHECK-NEXT: br i1 [[OR_COND_2_FROZEN]], label [[SELECT_END3:%.*]], label [[SELECT_FALSE4:%.*]] +; CHECK: select.false4: +; CHECK-NEXT: br label [[SELECT_END3]] +; CHECK: select.end3: +; CHECK-NEXT: [[TMP41:%.*]] = phi i32 [ [[TMP35]], [[SELECT_END1]] ], [ 3, [[SELECT_FALSE4]] ] +; CHECK-NEXT: [[DOT2_2:%.*]] = phi i1 [ [[DOT2_1]], [[SELECT_END1]] ], [ true, [[SELECT_FALSE4]] ] +; CHECK-NEXT: [[TMP42:%.*]] = phi i32 [ [[TMP36]], [[SELECT_END1]] ], [ [[TMP20]], [[SELECT_FALSE4]] ] ; CHECK-NEXT: [[NOT_OR_COND_2:%.*]] = xor i1 [[OR_COND_2]], true -; CHECK-NEXT: [[DOT2_2:%.*]] = select i1 [[NOT_OR_COND_2]], i1 true, i1 [[DOT2_1]] -; CHECK-NEXT: [[TMP42:%.*]] = select i1 [[OR_COND_2]], i32 [[TMP36]], i32 [[TMP20]] ; CHECK-NEXT: [[TMP43:%.*]] = getelementptr i8, ptr [[TMP25]], i64 [[DOTNEG50]] ; CHECK-NEXT: [[TMP44:%.*]] = load i32, ptr [[TMP43]], align 4 ; CHECK-NEXT: [[TMP45:%.*]] = icmp ne i32 [[TMP44]], [[TMP20]] ; CHECK-NEXT: [[TMP46:%.*]] = icmp sge i32 [[TMP44]], [[TMP42]] ; CHECK-NEXT: [[DOTNOT33_3:%.*]] = and i1 [[DOT2_2]], [[TMP46]] ; CHECK-NEXT: [[OR_COND_3:%.*]] = select i1 [[TMP45]], i1 true, i1 [[DOTNOT33_3]] -; CHECK-NEXT: [[TMP47:%.*]] = select i1 [[OR_COND_3]], i32 [[TMP41]], i32 4 +; CHECK-NEXT: [[OR_COND_3_FROZEN:%.*]] = freeze i1 [[OR_COND_3]] +; CHECK-NEXT: br i1 [[OR_COND_3_FROZEN]], label [[SELECT_END5:%.*]], label [[SELECT_FALSE6:%.*]] +; CHECK: select.false6: +; CHECK-NEXT: br label [[SELECT_END5]] +; CHECK: select.end5: +; CHECK-NEXT: [[TMP47:%.*]] = phi i32 [ [[TMP41]], [[SELECT_END3]] ], [ 4, [[SELECT_FALSE6]] ] +; CHECK-NEXT: [[DOT2_3:%.*]] = phi i1 [ [[DOT2_2]], [[SELECT_END3]] ], [ true, [[SELECT_FALSE6]] ] +; CHECK-NEXT: [[TMP48:%.*]] = phi i32 [ [[TMP42]], [[SELECT_END3]] ], [ [[TMP20]], [[SELECT_FALSE6]] ] ; CHECK-NEXT: [[NOT_OR_COND_3:%.*]] = xor i1 [[OR_COND_3]], true -; CHECK-NEXT: [[DOT2_3:%.*]] = select i1 [[NOT_OR_COND_3]], i1 true, i1 [[DOT2_2]] -; CHECK-NEXT: [[TMP48:%.*]] = select i1 [[OR_COND_3]], i32 [[TMP42]], i32 [[TMP20]] ; CHECK-NEXT: [[TMP49:%.*]] = getelementptr i8, ptr [[TMP25]], i64 [[DOTNEG51]] ; CHECK-NEXT: [[TMP50:%.*]] = load i32, ptr [[TMP49]], align 4 ; CHECK-NEXT: [[TMP51:%.*]] = icmp ne i32 [[TMP50]], [[TMP20]] ; CHECK-NEXT: [[TMP52:%.*]] = icmp sge i32 [[TMP50]], [[TMP48]] ; CHECK-NEXT: [[DOTNOT33_4:%.*]] = and i1 [[DOT2_3]], [[TMP52]] ; CHECK-NEXT: [[OR_COND_4:%.*]] = select i1 [[TMP51]], i1 true, i1 [[DOTNOT33_4]] -; CHECK-NEXT: [[TMP53:%.*]] = select i1 [[OR_COND_4]], i32 [[TMP47]], i32 5 +; CHECK-NEXT: [[OR_COND_4_FROZEN:%.*]] = freeze i1 [[OR_COND_4]] +; CHECK-NEXT: br i1 [[OR_COND_4_FROZEN]], label [[SELECT_END7:%.*]], label [[SELECT_FALSE8:%.*]] +; CHECK: select.false8: +; CHECK-NEXT: br label [[SELECT_END7]] +; CHECK: select.end7: +; CHECK-NEXT: [[TMP53:%.*]] = phi i32 [ [[TMP47]], [[SELECT_END5]] ], [ 5, [[SELECT_FALSE8]] ] +; CHECK-NEXT: [[DOT2_4:%.*]] = phi i1 [ [[DOT2_3]], [[SELECT_END5]] ], [ true, [[SELECT_FALSE8]] ] +; CHECK-NEXT: [[TMP54:%.*]] = phi i32 [ [[TMP48]], [[SELECT_END5]] ], [ [[TMP20]], [[SELECT_FALSE8]] ] ; CHECK-NEXT: [[NOT_OR_COND_4:%.*]] = xor i1 [[OR_COND_4]], true -; CHECK-NEXT: [[DOT2_4:%.*]] = select i1 [[NOT_OR_COND_4]], i1 true, i1 [[DOT2_3]] -; CHECK-NEXT: [[TMP54:%.*]] = select i1 [[OR_COND_4]], i32 [[TMP48]], i32 [[TMP20]] ; CHECK-NEXT: [[TMP55:%.*]] = getelementptr i8, ptr [[TMP25]], i64 [[DOTNEG52]] ; CHECK-NEXT: [[TMP56:%.*]] = load i32, ptr [[TMP55]], align 4 ; CHECK-NEXT: [[TMP57:%.*]] = icmp ne i32 [[TMP56]], [[TMP20]] ; CHECK-NEXT: [[TMP58:%.*]] = icmp sge i32 [[TMP56]], [[TMP54]] ; CHECK-NEXT: [[DOTNOT33_5:%.*]] = and i1 [[DOT2_4]], [[TMP58]] ; CHECK-NEXT: [[OR_COND_5:%.*]] = select i1 [[TMP57]], i1 true, i1 [[DOTNOT33_5]] -; CHECK-NEXT: [[TMP59:%.*]] = select i1 [[OR_COND_5]], i32 [[TMP53]], i32 6 +; CHECK-NEXT: [[OR_COND_5_FROZEN:%.*]] = freeze i1 [[OR_COND_5]] +; CHECK-NEXT: br i1 [[OR_COND_5_FROZEN]], label [[SELECT_END9:%.*]], label [[SELECT_FALSE10:%.*]] +; CHECK: select.false10: +; CHECK-NEXT: br label [[SELECT_END9]] +; CHECK: select.end9: +; CHECK-NEXT: [[TMP59:%.*]] = phi i32 [ [[TMP53]], [[SELECT_END7]] ], [ 6, [[SELECT_FALSE10]] ] +; CHECK-NEXT: [[DOT2_5:%.*]] = phi i1 [ [[DOT2_4]], [[SELECT_END7]] ], [ true, [[SELECT_FALSE10]] ] +; CHECK-NEXT: [[TMP60:%.*]] = phi i32 [ [[TMP54]], [[SELECT_END7]] ], [ [[TMP20]], [[SELECT_FALSE10]] ] ; CHECK-NEXT: [[NOT_OR_COND_5:%.*]] = xor i1 [[OR_COND_5]], true -; CHECK-NEXT: [[DOT2_5:%.*]] = select i1 [[NOT_OR_COND_5]], i1 true, i1 [[DOT2_4]] -; CHECK-NEXT: [[TMP60:%.*]] = select i1 [[OR_COND_5]], i32 [[TMP54]], i32 [[TMP20]] ; CHECK-NEXT: [[TMP61:%.*]] = getelementptr i8, ptr [[TMP25]], i64 [[DOTNEG53]] ; CHECK-NEXT: [[TMP62:%.*]] = load i32, ptr [[TMP61]], align 4 ; CHECK-NEXT: [[TMP63:%.*]] = icmp ne i32 [[TMP62]], [[TMP20]] ; CHECK-NEXT: [[TMP64:%.*]] = icmp sge i32 [[TMP62]], [[TMP60]] ; CHECK-NEXT: [[DOTNOT33_6:%.*]] = and i1 [[DOT2_5]], [[TMP64]] ; CHECK-NEXT: [[OR_COND_6:%.*]] = select i1 [[TMP63]], i1 true, i1 [[DOTNOT33_6]] -; CHECK-NEXT: [[TMP65:%.*]] = select i1 [[OR_COND_6]], i32 [[TMP59]], i32 7 +; CHECK-NEXT: [[OR_COND_6_FROZEN:%.*]] = freeze i1 [[OR_COND_6]] +; CHECK-NEXT: br i1 [[OR_COND_6_FROZEN]], label [[SELECT_END11:%.*]], label [[SELECT_FALSE12:%.*]] +; CHECK: select.false12: +; CHECK-NEXT: br label [[SELECT_END11]] +; CHECK: select.end11: +; CHECK-NEXT: [[TMP65:%.*]] = phi i32 [ [[TMP59]], [[SELECT_END9]] ], [ 7, [[SELECT_FALSE12]] ] +; CHECK-NEXT: [[DOT2_6:%.*]] = phi i1 [ [[DOT2_5]], [[SELECT_END9]] ], [ true, [[SELECT_FALSE12]] ] +; CHECK-NEXT: [[TMP66:%.*]] = phi i32 [ [[TMP60]], [[SELECT_END9]] ], [ [[TMP20]], [[SELECT_FALSE12]] ] ; CHECK-NEXT: [[NOT_OR_COND_6:%.*]] = xor i1 [[OR_COND_6]], true -; CHECK-NEXT: [[DOT2_6:%.*]] = select i1 [[NOT_OR_COND_6]], i1 true, i1 [[DOT2_5]] -; CHECK-NEXT: [[TMP66:%.*]] = select i1 [[OR_COND_6]], i32 [[TMP60]], i32 [[TMP20]] ; CHECK-NEXT: [[TMP67:%.*]] = getelementptr i8, ptr [[TMP25]], i64 [[DOTNEG54]] ; CHECK-NEXT: [[TMP68:%.*]] = load i32, ptr [[TMP67]], align 4 ; CHECK-NEXT: [[TMP69:%.*]] = icmp ne i32 [[TMP68]], [[TMP20]] ; CHECK-NEXT: [[TMP70:%.*]] = icmp sge i32 [[TMP68]], [[TMP66]] ; CHECK-NEXT: [[DOTNOT33_7:%.*]] = and i1 [[DOT2_6]], [[TMP70]] ; CHECK-NEXT: [[OR_COND_7:%.*]] = select i1 [[TMP69]], i1 true, i1 [[DOTNOT33_7]] -; CHECK-NEXT: [[TMP71:%.*]] = select i1 [[OR_COND_7]], i32 [[TMP65]], i32 8 +; CHECK-NEXT: [[OR_COND_7_FROZEN:%.*]] = freeze i1 [[OR_COND_7]] +; CHECK-NEXT: br i1 [[OR_COND_7_FROZEN]], label [[SELECT_END13:%.*]], label [[SELECT_FALSE14:%.*]] +; CHECK: select.false14: +; CHECK-NEXT: br label [[SELECT_END13]] +; CHECK: select.end13: +; CHECK-NEXT: [[TMP71:%.*]] = phi i32 [ [[TMP65]], [[SELECT_END11]] ], [ 8, [[SELECT_FALSE14]] ] +; CHECK-NEXT: [[DOT2_7:%.*]] = phi i1 [ [[DOT2_6]], [[SELECT_END11]] ], [ true, [[SELECT_FALSE14]] ] +; CHECK-NEXT: [[TMP72:%.*]] = phi i32 [ [[TMP66]], [[SELECT_END11]] ], [ [[TMP20]], [[SELECT_FALSE14]] ] ; CHECK-NEXT: [[NOT_OR_COND_7:%.*]] = xor i1 [[OR_COND_7]], true -; CHECK-NEXT: [[DOT2_7:%.*]] = select i1 [[NOT_OR_COND_7]], i1 true, i1 [[DOT2_6]] -; CHECK-NEXT: [[TMP72:%.*]] = select i1 [[OR_COND_7]], i32 [[TMP66]], i32 [[TMP20]] ; CHECK-NEXT: [[TMP73:%.*]] = getelementptr i8, ptr [[TMP25]], i64 [[DOTNEG55]] ; CHECK-NEXT: [[TMP74:%.*]] = load i32, ptr [[TMP73]], align 4 ; CHECK-NEXT: [[TMP75:%.*]] = icmp ne i32 [[TMP74]], [[TMP20]] ; CHECK-NEXT: [[TMP76:%.*]] = icmp sge i32 [[TMP74]], [[TMP72]] ; CHECK-NEXT: [[DOTNOT33_8:%.*]] = and i1 [[DOT2_7]], [[TMP76]] ; CHECK-NEXT: [[OR_COND_8:%.*]] = select i1 [[TMP75]], i1 true, i1 [[DOTNOT33_8]] -; CHECK-NEXT: [[TMP77]] = select i1 [[OR_COND_8]], i32 [[TMP71]], i32 9 +; CHECK-NEXT: [[OR_COND_8_FROZEN:%.*]] = freeze i1 [[OR_COND_8]] +; CHECK-NEXT: br i1 [[OR_COND_8_FROZEN]], label [[SELECT_END15]], label [[SELECT_FALSE16:%.*]] +; CHECK: select.false16: +; CHECK-NEXT: br label [[SELECT_END15]] +; CHECK: select.end15: +; CHECK-NEXT: [[TMP77]] = phi i32 [ [[TMP71]], [[SELECT_END13]] ], [ 9, [[SELECT_FALSE16]] ] +; CHECK-NEXT: [[DOT2_8]] = phi i1 [ [[DOT2_7]], [[SELECT_END13]] ], [ true, [[SELECT_FALSE16]] ] +; CHECK-NEXT: [[TMP78]] = phi i32 [ [[TMP72]], [[SELECT_END13]] ], [ [[TMP20]], [[SELECT_FALSE16]] ] ; CHECK-NEXT: [[NOT_OR_COND_8:%.*]] = xor i1 [[OR_COND_8]], true -; CHECK-NEXT: [[DOT2_8]] = select i1 [[NOT_OR_COND_8]], i1 true, i1 [[DOT2_7]] -; CHECK-NEXT: [[TMP78]] = select i1 [[OR_COND_8]], i32 [[TMP72]], i32 [[TMP20]] ; CHECK-NEXT: [[TMP79]] = add nuw nsw i64 [[TMP23]], 1 ; CHECK-NEXT: [[EXITCOND_NOT:%.*]] = icmp eq i64 [[TMP79]], [[TMP9]] ; CHECK-NEXT: br i1 [[EXITCOND_NOT]], label [[DOTPREHEADER]], label [[DOTPREHEADER35]] ; CHECK: .preheader: -; CHECK-NEXT: [[DOTLCSSA3641_LCSSA:%.*]] = phi i32 [ 0, [[TMP3:%.*]] ], [ [[TMP77]], [[DOTPREHEADER35]] ] +; CHECK-NEXT: [[DOTLCSSA3641_LCSSA:%.*]] = phi i32 [ 0, [[TMP3:%.*]] ], [ [[TMP77]], [[SELECT_END15]] ] ; CHECK-NEXT: ret i32 [[DOTLCSSA3641_LCSSA]] ; %4 = getelementptr i8, ptr %0, i64 40 -- GitLab From 990bed64fb2df0857471b954f9f9ef0e1a0a8fc4 Mon Sep 17 00:00:00 2001 From: Jay Foad Date: Wed, 22 May 2024 19:47:59 +0100 Subject: [PATCH 177/452] [AMDGPU] New intrinsic llvm.amdgcn.pops.exiting.wave.id (#89612) This provides access to the special scalar source value SRC_POPS_EXITING_WAVE_ID on GFX9 and GFX10. --- llvm/include/llvm/IR/IntrinsicsAMDGPU.td | 5 +++ llvm/lib/Target/AMDGPU/AMDGPUISelDAGToDAG.cpp | 11 ++++++ llvm/lib/Target/AMDGPU/AMDGPUISelDAGToDAG.h | 1 + .../AMDGPU/AMDGPUInstructionSelector.cpp | 17 ++++++++++ .../Target/AMDGPU/AMDGPUInstructionSelector.h | 1 + .../Target/AMDGPU/AMDGPURegisterBankInfo.cpp | 2 ++ .../llvm.amdgcn.pops.exiting.wave.id.ll | 34 +++++++++++++++++++ 7 files changed, 71 insertions(+) create mode 100644 llvm/test/CodeGen/AMDGPU/llvm.amdgcn.pops.exiting.wave.id.ll diff --git a/llvm/include/llvm/IR/IntrinsicsAMDGPU.td b/llvm/include/llvm/IR/IntrinsicsAMDGPU.td index 0b774b724d0c..5c001a4dd624 100644 --- a/llvm/include/llvm/IR/IntrinsicsAMDGPU.td +++ b/llvm/include/llvm/IR/IntrinsicsAMDGPU.td @@ -2482,6 +2482,11 @@ class AMDGPUGlobalLoadLDS : "", [SDNPMemOperand]>; def int_amdgcn_global_load_lds : AMDGPUGlobalLoadLDS; +// Use read/write of inaccessible memory to model the fact that this reads a +// volatile value. +def int_amdgcn_pops_exiting_wave_id : + DefaultAttrsIntrinsic<[llvm_i32_ty], [], [IntrInaccessibleMemOnly]>; + //===----------------------------------------------------------------------===// // GFX10 Intrinsics //===----------------------------------------------------------------------===// diff --git a/llvm/lib/Target/AMDGPU/AMDGPUISelDAGToDAG.cpp b/llvm/lib/Target/AMDGPU/AMDGPUISelDAGToDAG.cpp index c11c7a57e059..e35957338da7 100644 --- a/llvm/lib/Target/AMDGPU/AMDGPUISelDAGToDAG.cpp +++ b/llvm/lib/Target/AMDGPU/AMDGPUISelDAGToDAG.cpp @@ -2526,6 +2526,14 @@ void AMDGPUDAGToDAGISel::SelectDSBvhStackIntrinsic(SDNode *N) { CurDAG->setNodeMemRefs(cast(Selected), {MMO}); } +void AMDGPUDAGToDAGISel::SelectPOPSExitingWaveID(SDNode *N) { + // TODO: Select this with a tablegen pattern. This is tricky because the + // intrinsic is IntrReadMem/IntrWriteMem but the instruction is not marked + // mayLoad/mayStore and tablegen complains about the mismatch. + SDValue Reg = CurDAG->getRegister(AMDGPU::SRC_POPS_EXITING_WAVE_ID, MVT::i32); + CurDAG->SelectNodeTo(N, AMDGPU::S_MOV_B32, N->getVTList(), Reg); +} + static unsigned gwsIntrinToOpcode(unsigned IntrID) { switch (IntrID) { case Intrinsic::amdgcn_ds_gws_init: @@ -2682,6 +2690,9 @@ void AMDGPUDAGToDAGISel::SelectINTRINSIC_W_CHAIN(SDNode *N) { case Intrinsic::amdgcn_ds_bvh_stack_rtn: SelectDSBvhStackIntrinsic(N); return; + case Intrinsic::amdgcn_pops_exiting_wave_id: + SelectPOPSExitingWaveID(N); + return; } SelectCode(N); diff --git a/llvm/lib/Target/AMDGPU/AMDGPUISelDAGToDAG.h b/llvm/lib/Target/AMDGPU/AMDGPUISelDAGToDAG.h index f987b747c0e2..53d25b4cf4ca 100644 --- a/llvm/lib/Target/AMDGPU/AMDGPUISelDAGToDAG.h +++ b/llvm/lib/Target/AMDGPU/AMDGPUISelDAGToDAG.h @@ -274,6 +274,7 @@ private: void SelectFP_EXTEND(SDNode *N); void SelectDSAppendConsume(SDNode *N, unsigned IntrID); void SelectDSBvhStackIntrinsic(SDNode *N); + void SelectPOPSExitingWaveID(SDNode *N); void SelectDS_GWS(SDNode *N, unsigned IntrID); void SelectInterpP1F16(SDNode *N); void SelectINTRINSIC_W_CHAIN(SDNode *N); diff --git a/llvm/lib/Target/AMDGPU/AMDGPUInstructionSelector.cpp b/llvm/lib/Target/AMDGPU/AMDGPUInstructionSelector.cpp index b48a09489653..99109b23a159 100644 --- a/llvm/lib/Target/AMDGPU/AMDGPUInstructionSelector.cpp +++ b/llvm/lib/Target/AMDGPU/AMDGPUInstructionSelector.cpp @@ -2079,6 +2079,21 @@ bool AMDGPUInstructionSelector::selectDSBvhStackIntrinsic( return constrainSelectedInstRegOperands(*MIB, TII, TRI, RBI); } +bool AMDGPUInstructionSelector::selectPOPSExitingWaveID( + MachineInstr &MI) const { + Register Dst = MI.getOperand(0).getReg(); + const DebugLoc &DL = MI.getDebugLoc(); + MachineBasicBlock *MBB = MI.getParent(); + + // TODO: Select this with a tablegen pattern. This is tricky because the + // intrinsic is IntrReadMem/IntrWriteMem but the instruction is not marked + // mayLoad/mayStore and tablegen complains about the mismatch. + auto MIB = BuildMI(*MBB, &MI, DL, TII.get(AMDGPU::S_MOV_B32), Dst) + .addDef(AMDGPU::SRC_POPS_EXITING_WAVE_ID); + MI.eraseFromParent(); + return constrainSelectedInstRegOperands(*MIB, TII, TRI, RBI); +} + bool AMDGPUInstructionSelector::selectG_INTRINSIC_W_SIDE_EFFECTS( MachineInstr &I) const { unsigned IntrinsicID = cast(I).getIntrinsicID(); @@ -2129,6 +2144,8 @@ bool AMDGPUInstructionSelector::selectG_INTRINSIC_W_SIDE_EFFECTS( return selectSBarrierSignalIsfirst(I, IntrinsicID); case Intrinsic::amdgcn_s_barrier_leave: return selectSBarrierLeave(I); + case Intrinsic::amdgcn_pops_exiting_wave_id: + return selectPOPSExitingWaveID(I); } return selectImpl(I, *CoverageInfo); } diff --git a/llvm/lib/Target/AMDGPU/AMDGPUInstructionSelector.h b/llvm/lib/Target/AMDGPU/AMDGPUInstructionSelector.h index f561d5d29efc..48f3b1811801 100644 --- a/llvm/lib/Target/AMDGPU/AMDGPUInstructionSelector.h +++ b/llvm/lib/Target/AMDGPU/AMDGPUInstructionSelector.h @@ -125,6 +125,7 @@ private: bool selectDSAppendConsume(MachineInstr &MI, bool IsAppend) const; bool selectSBarrier(MachineInstr &MI) const; bool selectDSBvhStackIntrinsic(MachineInstr &MI) const; + bool selectPOPSExitingWaveID(MachineInstr &MI) const; bool selectImageIntrinsic(MachineInstr &MI, const AMDGPU::ImageDimIntrinsicInfo *Intr) const; diff --git a/llvm/lib/Target/AMDGPU/AMDGPURegisterBankInfo.cpp b/llvm/lib/Target/AMDGPU/AMDGPURegisterBankInfo.cpp index 56345d14a331..dbb42a60f71f 100644 --- a/llvm/lib/Target/AMDGPU/AMDGPURegisterBankInfo.cpp +++ b/llvm/lib/Target/AMDGPU/AMDGPURegisterBankInfo.cpp @@ -5132,6 +5132,8 @@ AMDGPURegisterBankInfo::getInstrMapping(const MachineInstr &MI) const { OpdsMapping[2] = getSGPROpMapping(MI.getOperand(2).getReg(), MRI, *TRI); break; } + case Intrinsic::amdgcn_pops_exiting_wave_id: + return getDefaultMappingSOP(MI); default: return getInvalidInstructionMapping(); } diff --git a/llvm/test/CodeGen/AMDGPU/llvm.amdgcn.pops.exiting.wave.id.ll b/llvm/test/CodeGen/AMDGPU/llvm.amdgcn.pops.exiting.wave.id.ll new file mode 100644 index 000000000000..4927c2ffcdf3 --- /dev/null +++ b/llvm/test/CodeGen/AMDGPU/llvm.amdgcn.pops.exiting.wave.id.ll @@ -0,0 +1,34 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 4 +; RUN: llc -global-isel=0 -mtriple=amdgcn -mcpu=gfx900 < %s | FileCheck %s -check-prefix=SDAG +; RUN: llc -global-isel=1 -mtriple=amdgcn -mcpu=gfx900 < %s | FileCheck %s -check-prefix=GFX9-GISEL +; RUN: llc -global-isel=0 -mtriple=amdgcn -mcpu=gfx1010 < %s | FileCheck %s -check-prefix=SDAG +; RUN: llc -global-isel=1 -mtriple=amdgcn -mcpu=gfx1010 < %s | FileCheck %s -check-prefix=GFX10-GISEL + +define amdgpu_ps void @test(ptr addrspace(1) inreg %ptr) { +; SDAG-LABEL: test: +; SDAG: ; %bb.0: +; SDAG-NEXT: s_mov_b32 s2, src_pops_exiting_wave_id +; SDAG-NEXT: v_mov_b32_e32 v0, 0 +; SDAG-NEXT: v_mov_b32_e32 v1, s2 +; SDAG-NEXT: global_store_dword v0, v1, s[0:1] +; SDAG-NEXT: s_endpgm +; +; GFX9-GISEL-LABEL: test: +; GFX9-GISEL: ; %bb.0: +; GFX9-GISEL-NEXT: s_mov_b32 s2, src_pops_exiting_wave_id +; GFX9-GISEL-NEXT: v_mov_b32_e32 v0, s2 +; GFX9-GISEL-NEXT: v_mov_b32_e32 v1, 0 +; GFX9-GISEL-NEXT: global_store_dword v1, v0, s[0:1] +; GFX9-GISEL-NEXT: s_endpgm +; +; GFX10-GISEL-LABEL: test: +; GFX10-GISEL: ; %bb.0: +; GFX10-GISEL-NEXT: s_mov_b32 s2, src_pops_exiting_wave_id +; GFX10-GISEL-NEXT: v_mov_b32_e32 v1, 0 +; GFX10-GISEL-NEXT: v_mov_b32_e32 v0, s2 +; GFX10-GISEL-NEXT: global_store_dword v1, v0, s[0:1] +; GFX10-GISEL-NEXT: s_endpgm + %id = call i32 @llvm.amdgcn.pops.exiting.wave.id() + store i32 %id, ptr addrspace(1) %ptr + ret void +} -- GitLab From f3dc732b3623c86164f9d95f7563f982cecc5558 Mon Sep 17 00:00:00 2001 From: Amir Ayupov Date: Wed, 22 May 2024 11:59:00 -0700 Subject: [PATCH 178/452] [BOLT][NFC] Make estimateEdgeCounts a BinaryFunctionPass (#93074) --- bolt/include/bolt/Passes/MCF.h | 17 +++++++++++++++-- bolt/lib/Passes/MCF.cpp | 24 +++++++++++++++++++++++- bolt/lib/Profile/DataReader.cpp | 2 -- bolt/lib/Profile/YAMLProfileReader.cpp | 4 +--- bolt/lib/Rewrite/BinaryPassManager.cpp | 9 +++++++++ 5 files changed, 48 insertions(+), 8 deletions(-) diff --git a/bolt/include/bolt/Passes/MCF.h b/bolt/include/bolt/Passes/MCF.h index 4b87401498fa..3fe674463bf1 100644 --- a/bolt/include/bolt/Passes/MCF.h +++ b/bolt/include/bolt/Passes/MCF.h @@ -9,10 +9,12 @@ #ifndef BOLT_PASSES_MCF_H #define BOLT_PASSES_MCF_H +#include "bolt/Passes/BinaryPasses.h" +#include "llvm/Support/CommandLine.h" + namespace llvm { namespace bolt { -class BinaryFunction; class DataflowInfoManager; /// Implement the idea in "SamplePGO - The Power of Profile Guided Optimizations @@ -23,7 +25,18 @@ void equalizeBBCounts(DataflowInfoManager &Info, BinaryFunction &BF); /// Fill edge counts based on the basic block count. Used in nonLBR mode when /// we only have bb count. -void estimateEdgeCounts(BinaryFunction &BF); +class EstimateEdgeCounts : public BinaryFunctionPass { + void runOnFunction(BinaryFunction &BF); + +public: + explicit EstimateEdgeCounts(const cl::opt &PrintPass) + : BinaryFunctionPass(PrintPass) {} + + const char *getName() const override { return "estimate-edge-counts"; } + + /// Pass entry point + Error runOnFunctions(BinaryContext &BC) override; +}; } // end namespace bolt } // end namespace llvm diff --git a/bolt/lib/Passes/MCF.cpp b/bolt/lib/Passes/MCF.cpp index b2723cd8dcb8..77dea7369140 100644 --- a/bolt/lib/Passes/MCF.cpp +++ b/bolt/lib/Passes/MCF.cpp @@ -12,9 +12,11 @@ #include "bolt/Passes/MCF.h" #include "bolt/Core/BinaryFunction.h" +#include "bolt/Core/ParallelUtilities.h" #include "bolt/Passes/DataflowInfoManager.h" #include "bolt/Utils/CommandLineOpts.h" #include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/STLExtras.h" #include "llvm/Support/CommandLine.h" #include #include @@ -432,7 +434,7 @@ void equalizeBBCounts(DataflowInfoManager &Info, BinaryFunction &BF) { } } -void estimateEdgeCounts(BinaryFunction &BF) { +void EstimateEdgeCounts::runOnFunction(BinaryFunction &BF) { EdgeWeightMap PredEdgeWeights; EdgeWeightMap SuccEdgeWeights; if (!opts::IterativeGuess) { @@ -453,5 +455,25 @@ void estimateEdgeCounts(BinaryFunction &BF) { recalculateBBCounts(BF, /*AllEdges=*/false); } +Error EstimateEdgeCounts::runOnFunctions(BinaryContext &BC) { + if (llvm::none_of(llvm::make_second_range(BC.getBinaryFunctions()), + [](const BinaryFunction &BF) { + return BF.getProfileFlags() == BinaryFunction::PF_SAMPLE; + })) + return Error::success(); + + ParallelUtilities::WorkFuncTy WorkFun = [&](BinaryFunction &BF) { + runOnFunction(BF); + }; + ParallelUtilities::PredicateTy SkipFunc = [&](const BinaryFunction &BF) { + return BF.getProfileFlags() != BinaryFunction::PF_SAMPLE; + }; + + ParallelUtilities::runOnEachFunction( + BC, ParallelUtilities::SchedulingPolicy::SP_BB_QUADRATIC, WorkFun, + SkipFunc, "EstimateEdgeCounts"); + return Error::success(); +} + } // namespace bolt } // namespace llvm diff --git a/bolt/lib/Profile/DataReader.cpp b/bolt/lib/Profile/DataReader.cpp index 06c5e96b7806..f2e999bbfdc6 100644 --- a/bolt/lib/Profile/DataReader.cpp +++ b/bolt/lib/Profile/DataReader.cpp @@ -598,8 +598,6 @@ void DataReader::readSampleData(BinaryFunction &BF) { } BF.ExecutionCount = TotalEntryCount; - - estimateEdgeCounts(BF); } void DataReader::convertBranchData(BinaryFunction &BF) const { diff --git a/bolt/lib/Profile/YAMLProfileReader.cpp b/bolt/lib/Profile/YAMLProfileReader.cpp index 29d94067f459..aa38dda47eb5 100644 --- a/bolt/lib/Profile/YAMLProfileReader.cpp +++ b/bolt/lib/Profile/YAMLProfileReader.cpp @@ -253,10 +253,8 @@ bool YAMLProfileReader::parseFunctionProfile( if (BB.getExecutionCount() == BinaryBasicBlock::COUNT_NO_PROFILE) BB.setExecutionCount(0); - if (YamlBP.Header.Flags & BinaryFunction::PF_SAMPLE) { + if (YamlBP.Header.Flags & BinaryFunction::PF_SAMPLE) BF.setExecutionCount(FunctionExecutionCount); - estimateEdgeCounts(BF); - } ProfileMatched &= !MismatchedBlocks && !MismatchedCalls && !MismatchedEdges; diff --git a/bolt/lib/Rewrite/BinaryPassManager.cpp b/bolt/lib/Rewrite/BinaryPassManager.cpp index cbb7199a53dd..0712330a524b 100644 --- a/bolt/lib/Rewrite/BinaryPassManager.cpp +++ b/bolt/lib/Rewrite/BinaryPassManager.cpp @@ -23,6 +23,7 @@ #include "bolt/Passes/JTFootprintReduction.h" #include "bolt/Passes/LongJmp.h" #include "bolt/Passes/LoopInversionPass.h" +#include "bolt/Passes/MCF.h" #include "bolt/Passes/PLTCall.h" #include "bolt/Passes/PatchEntries.h" #include "bolt/Passes/RegReAssign.h" @@ -90,6 +91,11 @@ PrintAfterLowering("print-after-lowering", cl::desc("print function after instruction lowering"), cl::Hidden, cl::cat(BoltOptCategory)); +static cl::opt PrintEstimateEdgeCounts( + "print-estimate-edge-counts", + cl::desc("print function after edge counts are set for no-LBR profile"), + cl::Hidden, cl::cat(BoltOptCategory)); + cl::opt PrintFinalized("print-finalized", cl::desc("print function after CFG is finalized"), @@ -334,6 +340,9 @@ Error BinaryFunctionPassManager::runPasses() { Error BinaryFunctionPassManager::runAllPasses(BinaryContext &BC) { BinaryFunctionPassManager Manager(BC); + Manager.registerPass( + std::make_unique(PrintEstimateEdgeCounts)); + const DynoStats InitialDynoStats = getDynoStats(BC.getBinaryFunctions(), BC.isAArch64()); -- GitLab From ff3f41deb04c03ba57658776e4e0dc26ef01187d Mon Sep 17 00:00:00 2001 From: Matheus Izvekov Date: Wed, 22 May 2024 15:59:55 -0300 Subject: [PATCH 179/452] [clang] Implement CWG2398 provisional TTP matching to class templates (#92855) This solves some ambuguity introduced in P0522 regarding how template template parameters are partially ordered, and should reduce the negative impact of enabling `-frelaxed-template-template-args` by default. When performing template argument deduction, we extend the provisional wording introduced in https://github.com/llvm/llvm-project/pull/89807 so it also covers deduction of class templates. Given the following example: ```C++ template struct A; template struct B; template